home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 318_01 / reded.c < prev    next >
C/C++ Source or Header  |  1990-06-18  |  20KB  |  1,208 lines

  1. /*
  2.     RED window module -- Full C version
  3.  
  4.     Source:  reded.c
  5.     Version: March 28, 1986; January 18, 1990;
  6.  
  7.     Written by
  8.     
  9.         Edward K. Ream
  10.         166 N. Prospect
  11.         Madison WI 53705
  12.         (608) 257-0802
  13.  
  14.  
  15.     PUBLIC DOMAIN SOFTWARE
  16.  
  17.     This software is in the public domain.
  18.  
  19.     See red.h for a disclaimer of warranties and other information.
  20. */
  21.  
  22. #include "red.h"
  23.  
  24. /*
  25.     Declare routines local to this module.
  26. */
  27. static void    edadj    (void);
  28. static void    edredraw(void);
  29. static int    edscan    (int xpos);
  30. static void    ed_sup    (int topline);
  31. static void    ed_sdn    (int topline);
  32. static void    ed_ind    (void);
  33. static void    ed_inu    (void);
  34. static void    ed_del    (void);
  35.  
  36. /*
  37.     Declare variables local to this module.
  38. */
  39. static char    editbuf[MAXLEN];    /* the edit buffer    */
  40. static int    editp;            /* cursor: buffer index    */
  41. static int    editpmax;        /* length of buffer    */
  42. static int    edcflag;        /* buffer change flag    */
  43. static int    edaflag;        /* auto mode flag    */
  44. static int    edtop;            /* current top of screen */
  45.  
  46. /*
  47.     True if the current edit line is displayed at bottom of screen.
  48. */
  49. #define edatbot() (outy == SCRNL1)
  50. #define edattop() (outy == 1)
  51.  
  52. /* The x position of the cursor on screen. */
  53. #define edxpos() (fmtcol[editp])
  54.  
  55. /*
  56.     Abort any changes made to current line.
  57. */
  58. void
  59. edabt(void)
  60. {
  61.     TICKB("edabt");
  62.  
  63.     /* Get unchanged line and reset cursor. */
  64.     edgetln();
  65.     edredraw();
  66.     edbegin();
  67.     edcflag = FALSE;
  68.  
  69.     TICKX("edabt");
  70. }
  71.  
  72. /*
  73.     Put cursor at beginning of current line.
  74. */
  75. void
  76. edbegin(void)
  77. {
  78.         TICKB("edbegin");
  79.  
  80.         editp = 0;
  81.     outxy(0, outy);
  82.  
  83.     TICKX("edbegin");
  84. }
  85.  
  86. /*
  87.     Move the cursor back one word.
  88. */
  89. void
  90. edbword(void)
  91. {
  92.     int c;
  93.  
  94.     TICKB("edbword");
  95.  
  96.     /* Move up one line if at left margin. */
  97.     if (editp == 0) {
  98.         if (!bufattop()) {
  99.             edup();       
  100.             edend();
  101.         }
  102.         RETURN_VOID("edbword");
  103.     }
  104.  
  105.     /* Scan for white space. */
  106.     while (--editp > 0) {
  107.         c = editbuf [editp];
  108.         if (c == ' ' || c == '\t') {
  109.             break;
  110.         }
  111.     }
  112.  
  113.     /* Scan for non-white space. */
  114.     while (editp > 0) {
  115.         c = editbuf [--editp];
  116.         if (c != ' ' && c != '\t') {
  117.             break;
  118.         }
  119.     }
  120.  
  121.     /* Reset cursor. */
  122.     outxy(edxpos(), outy);
  123.  
  124.     TICKX("edbword");
  125. }
  126.  
  127. /*
  128.     Change editbuf[editp] to c.
  129.     Don't make change if line would become to long.
  130. */
  131. void
  132. edchng(c)
  133. char c;
  134. {
  135.     char oldc;
  136.     int k;
  137.  
  138.     TRACEPB("edchng", sl_lpout(); sl_cout(c); sl_rpout());
  139.  
  140.     /* If at right margin then insert char. */
  141.     if (editp >= editpmax) {
  142.         edins(c);
  143.         RETURN_VOID("edchng");
  144.     }
  145.  
  146.     /* Change char and print length of line. */
  147.     oldc = editbuf[editp];
  148.     editbuf[editp] = c;
  149.     fmtadj(editbuf, editp, editpmax);
  150.  
  151.     k = fmtcol[editp+1];
  152.     if (k > SCRNW1) {
  153.  
  154.         /*
  155.             The line would become too long.
  156.             Undo the change.
  157.         */
  158.         editbuf[editp] = oldc;
  159.         fmtadj(editbuf, editp, editpmax);
  160.     }
  161.     else {
  162.         /* Set change flag, bump cursor, redraw line. */
  163.         edcflag = TRUE;
  164.         editp++;
  165.         edadj();
  166.         edredraw();
  167.     }
  168.  
  169.     TICKX("edchng");
  170. }
  171.  
  172. /*
  173.     Indicate that the screen has been changed by
  174.     an agent outside of this module.
  175. */
  176. void
  177. edclr(void)
  178. {
  179.     TICKB("edclr");
  180.  
  181.     edtop = -1;
  182.  
  183.     TICKX("edclr");
  184. }
  185.  
  186. /*
  187.     Delete the char to left of cursor if it exists.
  188. */
  189. void
  190. eddel(void)
  191. {
  192.     int i, k;
  193.  
  194.     TICKB("eddel");
  195.  
  196.     /* Just move left one column if past end of line. */
  197.     if (edxpos() < outx) {
  198.         outxy(outx-1, outy);
  199.         RETURN_VOID("eddel");
  200.     }
  201.  
  202.     /* Do nothing if cursor is at left margin. */
  203.     if (editp == 0) {
  204.         RETURN_VOID("eddel");
  205.     }
  206.     edcflag = TRUE;
  207.  
  208.     /* Compress buffer (delete char). */
  209.     k = editp;
  210.     while (k < editpmax) {
  211.         editbuf[k-1] = editbuf[k];
  212.         k++;
  213.     }
  214.  
  215.     /* Update pointers, update line. */
  216.     editp--;
  217.     editpmax--;
  218.     edredraw();
  219.  
  220.     TICKX("eddel");
  221. }
  222.  
  223. /*
  224.     Delete the character under the cursor.
  225. */
  226. void
  227. ed2del(void)
  228. {
  229.     int i, k;
  230.  
  231.     TICKB("ed2del");
  232.  
  233.     /* Just move left one column if past end of line. */
  234.     if (editp > 0 && editp == editpmax && edxpos() <= outx) {
  235.         outxy(outx-1, outy);
  236.         RETURN_VOID("ed2del");
  237.     }
  238.  
  239.     /* Do nothing if cursor is at left margin. */
  240.     if (editpmax == 0) {
  241.         RETURN_VOID("ed2del");
  242.     }
  243.     edcflag = TRUE;
  244.  
  245.     /* Compress buffer (delete char). */
  246.     k = editp+1;
  247.     while (k < editpmax) {
  248.         editbuf[k-1] = editbuf[k];
  249.         k++;
  250.     }
  251.  
  252.     /* Adjust the cursor if now at end. */
  253.     if (editp+1 >= editpmax && editp > 0) {
  254.         editp--;
  255.     }
  256.     editpmax--;
  257.     if (editp == editpmax && editp > 0) {
  258.         editp--;
  259.     }
  260.     edredraw();
  261.  
  262.     TICKX("ed2del");
  263. }
  264.  
  265. /*
  266.     Edit the next line.  Do not go to end of buffer.
  267. */
  268. void
  269. eddn(void)
  270. {
  271.     int oldx;
  272.  
  273.     TICKB("eddn");
  274.  
  275.     /* Save visual position of cursor. */
  276.     oldx = outx;
  277.  
  278.     /* Replace current edit line. */
  279.     edrepl();
  280.  
  281.     /* Do not go past last non-null line. */
  282.     if (bufnrbot()) {
  283.         if (edatbot()) {
  284.             ed_sup(bufln()-SCRNL2+1);
  285.             bufout(bufln() + 1, SCRNL1, 1);
  286.             outxy(0, SCRNL2);
  287.         }
  288.         RETURN_VOID("eddn");
  289.     }
  290.  
  291.     /* Move down one line in buffer. */
  292.     bufdn();
  293.     edgetln();
  294.  
  295.     /*
  296.         Put cursor as close as possible on this
  297.         new line to where it was on the old line.
  298.     */
  299.  
  300.     editp = edscan(oldx);
  301.  
  302.     /* Update screen. */
  303.     if (edatbot()) {
  304.         ed_sup(bufln()-SCRNL2);
  305.         outxy(oldx, SCRNL1);
  306.     }
  307.     else {
  308.         outxy(oldx, outy+1);
  309.     }
  310.  
  311.     RETURN_VOID("eddn");
  312. }
  313.  
  314. /*
  315.     Put cursor at the end of the current line.
  316.     Make sure it doesn't go off the screen.
  317. */
  318. void
  319. edend(void)
  320. {
  321.     TICKB("edend");
  322.  
  323.     editp = editpmax;
  324.     edadj();
  325.     outxy(edxpos(), outy);
  326.  
  327.     TICKX("edend");
  328. }
  329.  
  330. /*
  331.     Move the cursor forward one word.
  332.     Move to the next line if at end of line.
  333. */
  334. void
  335. edfword(void)
  336. {
  337.     int c;
  338.  
  339.     TICKB("edfword");
  340.  
  341.     /* Move down one line if at right margin. */
  342.     if (editp == editpmax) {
  343.         eddn();
  344.         edbegin();
  345.         RETURN_VOID("edfword");
  346.     }
  347.  
  348.     /* Scan for white space. */
  349.     while (++editp < editpmax) {
  350.         c = editbuf [editp];
  351.         if (c == ' ' || c == '\t') {
  352.             break;
  353.         }
  354.     }
  355.  
  356.     /* Scan for non-white space. */
  357.     while (editp < editpmax) {
  358.         c = editbuf [++editp];
  359.         if (c != ' ' && c != '\t') {
  360.             break;
  361.         }
  362.     }
  363.  
  364.     /* Reset cursor. */
  365.     edadj();
  366.     outxy(edxpos(), outy);
  367.  
  368.     TICKX("edfword");
  369. }
  370.  
  371. /*
  372.     Fill edit buffer from current main buffer line.
  373.     The caller must check to make sure the main
  374.     buffer is available.
  375. */
  376. void
  377. edgetln(void)
  378. {
  379.     int k;
  380.  
  381.     TICKB("edgetln");
  382.  
  383.     /* Put cursor on left margin, reset flag. */
  384.     editp = 0;
  385.     edcflag = FALSE;
  386.  
  387.     /* Get edit line from main buffer. */
  388.     k = bufgetln(editbuf,MAXLEN);
  389.     if (k > MAXLEN) {
  390.         error("line truncated");
  391.         editpmax = MAXLEN;
  392.     }
  393.     else {
  394.         editpmax = k;
  395.     }
  396.     fmtadj(editbuf,0,editpmax);
  397.  
  398.     TICKX("edgetln");
  399. }
  400.  
  401. /*
  402.     Start editing line n;  set editp to x.
  403.  
  404.     At one time I thought that the search and change
  405.     commands needed a separate version of this routine
  406.     that would try to draw the line at the top of the
  407.     screen.  However,  that did not provide enough
  408.     context for the person looking at the patterns.
  409. */
  410. void
  411. edgo(newline, x)
  412. int newline, x;
  413. {
  414.     int line;
  415.     int oldlast;
  416.  
  417.     TRACEPB("edgo",  sl_lpout();
  418.         sl_iout(newline); sl_csout();
  419.         sl_iout(x);       sl_rpout());
  420.  
  421.     /* Save the status of the screen. */
  422.     oldlast  = edtop + SCRNL2;
  423.  
  424.     /* Replace current line. */
  425.     edrepl();
  426.  
  427.     /* Go to new line. */
  428.     bufgo(newline);
  429.  
  430.     /* Prevent going past end of buffer. */
  431.     if (bufatbot()) {
  432.         bufup();
  433.     }
  434.     newline = bufln();
  435.  
  436.     /* Do not redraw the whole screen if not needed. */
  437.     if (edtop > 0 && newline >= edtop && newline <= oldlast) {
  438.         /* Just move to new line. */
  439.         line = 1 + (newline - edtop);
  440.     }
  441.     else if (bufln() + SCRNL/2 > bufmax()) {
  442.         /* The line is near the end of file. */
  443.         edtop = max(1,  bufmax() - (SCRNL-3));
  444.         line = 1 + (bufln() - edtop);
  445.         bufout(edtop, 1, SCRNL1);
  446.     }
  447.     else {
  448.         /* Draw the line in the middle of the screen. */
  449.         edtop = max(1, bufln() - SCRNL/2);
  450.         line  = 1 + (bufln() - edtop);
  451.         bufout(edtop, 1, SCRNL1);
  452.     }
  453.  
  454.     edgetln();
  455.     editp = x;
  456.     outxy(edxpos(), line);
  457.  
  458.     TICKX("edgo");
  459. }
  460.  
  461. /*
  462.     Insert c into the buffer if possible.
  463.     Return TRUE if the line was auto-split.
  464. */
  465. int
  466. edins(char c)
  467. {
  468.     int i, k;
  469.     int oldcflag;
  470.  
  471.     TRACEPB("edins", sl_lpout(); sl_cout(c); sl_rpout());
  472.  
  473.     /* Do nothing if edit buffer is full. */
  474.     if (editpmax >= MAXLEN) {
  475.         RETURN_INT("edins", FALSE);
  476.     }
  477.  
  478.     /* Provisionally say we've made a change. */
  479.     oldcflag = edcflag;
  480.     edcflag  = TRUE;
  481.  
  482.     /* Fill out line if we are past its end. */
  483.     if (editp == editpmax && edxpos() < outx) {
  484.         k = outx - edxpos();
  485.         editpmax = editpmax + k;
  486.         while (k-- > 0) {
  487.             editbuf [editp++] = ' ';
  488.         }
  489.         editp = editpmax;
  490.     }
  491.  
  492.     /* Make room for inserted character. */
  493.     k = editpmax;
  494.     while (k > editp) {
  495.         editbuf[k] = editbuf[k-1];
  496.         k--;
  497.     }
  498.  
  499.     /* Insert character.  Update pointers. */
  500.     editbuf[editp] = c;
  501.     editp++;
  502.     editpmax++;
  503.  
  504.     /* Find where the cursor will be. */
  505.     fmtadj(editbuf,editp-1,editpmax);
  506.     k = fmtcol[editp];
  507.  
  508.     if (k > SCRNW1 && editp == editpmax && haswrap) {
  509.         /* Auto-split the line (line wrap) */
  510.  
  511.         /* Scan for start of current word. */
  512.         k = editp - 1;
  513.         while (k >= 0 && editbuf[k] != ' ' && editbuf[k] != '\t') {
  514.             k--;
  515.         }
  516.  
  517.         /* Never split a word. */
  518.         if (k < 0) {
  519.             eddel();
  520.             edcflag = oldcflag;
  521.             RETURN_INT("edins", FALSE);
  522.         }
  523.  
  524.         /* Split the line at the current word. */
  525.         editp = k + 1;
  526.         edsplit();
  527.         edend();
  528.         RETURN_INT("edins", TRUE);
  529.     }
  530.     else if (k > SCRNW1) {
  531.  
  532.         /*
  533.             Cursor would move off the screen.
  534.             Delete what we just inserted.
  535.         */
  536.         eddel();
  537.         edcflag = oldcflag;
  538.     }
  539.     else {
  540.         /* Set change flag, redraw line. */
  541.         edredraw();
  542.     }
  543.     RETURN_INT("edins", FALSE);
  544. }
  545.  
  546. /*
  547.     Join (concatenate) the current line with the one above it.
  548.     Put cursor at the join point unless it would be off screen.
  549. */
  550. void
  551. edjoin(void)
  552. {
  553.     int k1, k2;
  554.     int k;
  555.  
  556.     TICKB("edjoin");
  557.  
  558.     /* Do nothing if at top of file. */
  559.     if (bufattop()) {
  560.         RETURN_VOID("edjoin");
  561.     }
  562.  
  563.     /* Replace lower line temporarily. */
  564.     edrepl();
  565.  
  566.     /* Get upper line into buffer. */
  567.     bufup();
  568.     k1 = bufgetln(editbuf, MAXLEN);
  569.  
  570.     /* Append lower line to buffer. */
  571.     bufdn();
  572.     k2 = bufgetln(editbuf+k1, MAXLEN-k1);
  573.  
  574.     /* Abort if the line isn't wide enough. */
  575.     if (k1 + k2 > MAXLEN1) {
  576.         bufgetln(editbuf,MAXLEN);
  577.         RETURN_VOID("edjoin");
  578.     }
  579.  
  580.     /* Replace upper line, set cursor to middle of line. */
  581.     bufup();
  582.     editpmax = k1 + k2;
  583.     editp = k1;
  584.     edadj();
  585.     edcflag = TRUE;
  586.     edrepl();
  587.  
  588.     /* Delete the lower line from the buffer. */
  589.     bufdn();
  590.     bufdel();
  591.  
  592.     /*
  593.         Delete the lower line on the screen,
  594.         move up and redraw.
  595.     */
  596.         
  597.     if (!edattop()) {
  598.         ed_del();
  599.         outxy(outx, outy - 1);
  600.         bufup();
  601.         edredraw();
  602.     }
  603.     else {
  604.         bufup();
  605.         edtop = bufln();
  606.  
  607.         /* Redraw the ENTIRE line. */
  608.         fmtadj (editbuf,0,editpmax);
  609.         fmtsubs(editbuf,0,editpmax);
  610.         outxy(edxpos(), outy);
  611.     }
  612.  
  613.     TICKX("edjoin");
  614. }
  615.  
  616. /*
  617.     Delete WORDS until end of line or c found.
  618. */
  619. void
  620. edkill(char c)
  621. {
  622.     int k,p;
  623.     int lastc;
  624.  
  625.     TRACEPB("edkill", sl_lpout(); sl_cout(c); sl_rpout());
  626.  
  627.     /* Do nothing if at right margin. */
  628.     if (editp == editpmax) {
  629.         RETURN_VOID("edkill");
  630.     }
  631.     edcflag = TRUE;
  632.  
  633.     /*
  634.         Count number of deleted characters.
  635.         The matched char must start a word.
  636.     */
  637.     k = 1;
  638.     lastc = ' ';
  639.     while ((editp+k) < editpmax) {
  640.         if ( editbuf[editp+k] == c &&
  641.              (!isalpha(lastc) || !isalpha(c))
  642.            ) {
  643.             break;
  644.         }
  645.         else {
  646.             lastc = editbuf[editp+k];
  647.             k++;
  648.         }
  649.     }
  650.  
  651.     /* Compress buffer (delete chars). */
  652.     p = editp+k;
  653.     while (p < editpmax) {
  654.         editbuf[p-k] = editbuf[p];
  655.         p++;
  656.     }
  657.  
  658.     /* Update buffer size, redraw line. */
  659.     editpmax = editpmax-k;
  660.     edredraw();
  661.  
  662.     TICKX("edkill");
  663. }
  664.  
  665. /*
  666.     Move cursor left one column.
  667.     Never move the cursor off the current line.
  668. */
  669. void
  670. edleft(void)
  671. {
  672.     int k;
  673.  
  674.     TICKB("edleft");
  675.  
  676.     /* If past right margin, move left one column. */
  677.     if (edxpos() < outx) {
  678.         outxy(max(0, outx-1), outy);
  679.     }
  680.  
  681.     /* Inside the line.  move left one character. */
  682.     else if (editp != 0) {
  683.         editp--;
  684.         outxy(edxpos(), outy);
  685.     }
  686.  
  687.     TICKX("edleft");
  688. }
  689.  
  690. /*
  691.     Insert a new blank line below the current line.
  692. */
  693. void
  694. ednewdn(void)
  695. {
  696.     TICKB("ednewdn");
  697.  
  698.     /*
  699.         Make sure there is a current line and 
  700.         Put the current line back into the buffer.
  701.     */
  702.  
  703.     if (bufatbot()) {
  704.         bufins(editbuf,editpmax);
  705.     }
  706.     edrepl();
  707.  
  708.     /* Move past current line. */
  709.     bufdn();
  710.  
  711.     /* Insert place holder:  zero length line. */
  712.     bufins(editbuf,0);
  713.  
  714.     /* Start editing the zero length line. */
  715.     edgetln();
  716.  
  717.     /* Update the screen. */
  718.     ed_ind();
  719.  
  720.     TICKX("ednewdn");
  721. }
  722.  
  723. /*
  724.     Insert a new blank line above the current line.
  725. */
  726. void
  727. ednewup(void)
  728. {
  729.     TICKB("ednewup");
  730.  
  731.     /* Put current line back in buffer. */
  732.     edrepl();
  733.  
  734.     /* Insert zero length line at current line. */
  735.     bufins(editbuf,0);
  736.  
  737.     /* Start editing the zero length line. */
  738.     edgetln();
  739.  
  740.     /* Update the screen. */
  741.     ed_inu();
  742.  
  743.     TICKX("ednewup");
  744. }
  745.  
  746. /*
  747.     Replace current main buffer line by edit buffer.
  748.     The edit buffer is NOT changed or cleared.
  749. */
  750. void
  751. edrepl(void)
  752. {
  753.     TICKB("edrepl");
  754.  
  755.     /* Do nothing if nothing has changed. */
  756.     if (edcflag == FALSE) {
  757.         RETURN_VOID("edrepl");
  758.     }
  759.  
  760.     /* Make sure we don't replace the line twice. */
  761.     edcflag = FALSE;
  762.  
  763.     /* Insert instead of replace if at bottom of file. */
  764.     if (bufatbot()) {
  765.         bufins(editbuf,editpmax);
  766.     }
  767.     else {
  768.         bufrepl(editbuf,editpmax);
  769.     }
  770.  
  771.     TICKX("edrepl");
  772. }
  773.  
  774. /*
  775.     Move cursor right one character.
  776.     Never move the cursor off the current line.
  777. */
  778. void
  779. edright(void)
  780. {
  781.     TICKB("edright");
  782.  
  783.     /* If we are outside the line move right one column. */
  784.     if (edxpos() < outx) {
  785.         outxy (min(SCRNW1, outx+1), outy);
  786.     }
  787.  
  788.     /* If we are inside a tab move to the end of it. */
  789.     else if (edxpos() > outx) {
  790.         outxy (edxpos(), outy);
  791.     }
  792.  
  793.     /* Move right one character if inside line. */
  794.     else if (editp < editpmax) {
  795.         editp++;
  796.         edadj();
  797.         outxy(edxpos(), outy);
  798.     }
  799.  
  800.     /* Else move past end of line. */
  801.     else {
  802.         outxy (min(SCRNW1, outx+1), outy);
  803.     }
  804.  
  805.     TICKX("edright");
  806. }
  807.  
  808. /*
  809.     Split the current line into two parts.
  810.     Scroll the first half of the old line up.
  811. */
  812. void
  813. edsplit(void)
  814. {
  815.     int p, q;
  816.     int k;
  817.  
  818.     TICKB("edsplit");
  819.  
  820.     /* Indicate that edit buffer has been saved. */
  821.     edcflag = FALSE;
  822.  
  823.     /* Replace current line by the first half of line. */
  824.     if (bufatbot()) {
  825.         bufins(editbuf, editp);
  826.     }
  827.     else {
  828.         bufrepl(editbuf, editp);
  829.     }
  830.  
  831.     /* Redraw the first half of the line. */
  832.     p = editpmax;
  833.     q = editp;
  834.     editpmax = editp;
  835.     editp = 0;
  836.     edredraw();
  837.  
  838.     /* Move the second half of the line down. */
  839.     editp = 0;
  840.     while (q < p) {
  841.         editbuf [editp++] = editbuf [q++];
  842.     }
  843.     editpmax = editp;
  844.     editp = 0;
  845.  
  846.     /* Insert second half of the line below the first. */
  847.     bufdn();
  848.     bufins(editbuf, editpmax);
  849.  
  850.     /* Insert a line on the screen and draw it. */
  851.     ed_ind();
  852.     edredraw();
  853.  
  854.     TICKX("edsplit");
  855. }
  856.  
  857. /*
  858.     Move cursor right until end of line or char c found.
  859.     Do not move the cursor off the end of the line.
  860. */
  861. void
  862. edsrch(char c)
  863. {
  864.     int lastc;
  865.  
  866.     TRACEPB("edsrch", sl_lpout(); sl_cout(c); sl_rpout());
  867.  
  868.     /* Do nothing if at right margin. */
  869.     if (editp == editpmax) {
  870.         RETURN_VOID("edsrch");
  871.     }
  872.  
  873.     /* Scan for search character. */
  874.     editp++;
  875.     if (editpmax == 0) {
  876.         lastc = ' ';
  877.     }
  878.     else {
  879.         /* 3/28/86 */
  880.         lastc = editbuf [editp];
  881.     }
  882.     while (editp < editpmax) {
  883.         if ( editbuf[editp] == c &&
  884.              (!isalpha(lastc) || !isalpha(c))
  885.            ) {
  886.             break;
  887.         }
  888.         else {
  889.             lastc = editbuf[editp];
  890.             editp++;
  891.         }
  892.     }
  893.  
  894.     /* Reset cursor. */
  895.     edadj();
  896.     outxy(edxpos(), outy);
  897.  
  898.     TICKX("edsrch");
  899. }
  900.  
  901. /*
  902.     Move cursor up one line if possible.
  903. */
  904. void
  905. edup(void)
  906. {
  907.     int oldx;
  908.  
  909.     TICKB("edup");
  910.  
  911.     /* Save visual position of cursor. */
  912.     oldx = outx;
  913.  
  914.     /* Put current line back in buffer. */
  915.     edrepl();
  916.  
  917.     /* Done if at top of buffer. */
  918.     if (bufattop()) {
  919.         RETURN_VOID("edup");
  920.     }
  921.  
  922.     /* Start editing the previous line. */
  923.     bufup();
  924.     edgetln();
  925.  
  926.     /*
  927.         Put cursor on this new line as close as
  928.         possible to where it was on the old line.
  929.     */
  930.     editp = edscan(oldx);
  931.  
  932.     /* Update screen. */
  933.     if (edattop()) {
  934.         ed_sdn(bufln());
  935.         outxy(oldx, 1);
  936.     }
  937.     else {
  938.         outxy(oldx, outy-1);
  939.     }
  940.  
  941.     TICKX("edup");
  942. }
  943.  
  944. /*
  945.     Delete the current line.
  946. */
  947. void
  948. edzap(void)
  949. {
  950.     int k;
  951.  
  952.     TICKB("edzap");
  953.  
  954.     /* Delete the line in the buffer. */
  955.     bufdel();
  956.  
  957.     /* Move up one line if now at bottom. */
  958.     if (bufatbot() && edattop()) {
  959.         bufup();
  960.         edtop = bufln();
  961.         edgetln();
  962.         edredraw();
  963.     }
  964.     else if (bufatbot()) {
  965.         ed_del();
  966.         outxy(0, outy - 1);
  967.         bufup();
  968.         edgetln();
  969.     }
  970.     else {
  971.         ed_del();
  972.         edgetln();
  973.     }
  974.  
  975.     TICKX("edzap");
  976. }
  977.  
  978.  
  979. /* ----- utility routines (not used outside this file) ----- */
  980.  
  981.  
  982. /*
  983.     Adjust the cursor position so the cursor stays on screen.
  984.     This must be called whenever the cursor could move right,
  985.     i.e., in edchng(), edend(), edjoin(), edright() and edsrch().
  986. */
  987. static void
  988. edadj(void)
  989. {
  990.     TICKB("edadj");
  991.  
  992.     while (fmtcol[editp] > SCRNW1) {
  993.         editp--;
  994.     }
  995.  
  996.     TICKX("edadj");
  997. }
  998.  
  999.  
  1000. /*
  1001.     Redraw edit line from index to end of line and
  1002.     reposition cursor.
  1003. */
  1004. static void
  1005. edredraw(void)
  1006. {
  1007.     TICKB("edredraw");
  1008.  
  1009.     fmtadj(editbuf,0,editpmax);
  1010.     fmtsubs(editbuf,max(0,editp-1),editpmax);
  1011.     outxy(edxpos(), outy);
  1012.  
  1013.     TICKX("edredraw");
  1014. }
  1015.  
  1016. /*
  1017.     Set editp to the largest index such that
  1018.     buf[editp] will be printed <= xpos
  1019. */
  1020. static int
  1021. edscan(int xpos)
  1022. {
  1023.     TRACEPB("edscan", sl_lpout(); sl_iout(xpos); sl_rpout());
  1024.  
  1025.     editp = 0;
  1026.     while (editp < editpmax) {
  1027.         if (fmtcol[editp] < xpos) {
  1028.             editp++;
  1029.         }
  1030.         else {
  1031.             break;
  1032.         }
  1033.     }
  1034.  
  1035.     RETURN_INT("edscan", editp);
  1036. }
  1037.  
  1038. /*
  1039.     Scroll the screen up.  Topline will be new top line.
  1040. */
  1041. static void
  1042. ed_sup(int topline)
  1043. {
  1044.     TRACEPB("ed_sup", sl_lpout(); sl_iout(topline); sl_rpout());
  1045.  
  1046.     edtop = topline;
  1047.     if (hasdel == TRUE) {
  1048.  
  1049.         /* Delete line 1. */
  1050.         outxy(0, 1);
  1051.         outdel();
  1052.  
  1053.         /* Redraw bottom line. */
  1054.         bufout(topline+SCRNL2,SCRNL1,1);
  1055.     }
  1056.     else if (hasup == TRUE) {
  1057.  
  1058.         /* Hardware scroll. */
  1059.         outsup();
  1060.  
  1061.         /* Redraw bottom line. */
  1062.         bufout(topline+SCRNL2,SCRNL1,1);
  1063.  
  1064.         /* Restore the prompt line. */
  1065.         pmtzap();
  1066.     }
  1067.     else {
  1068.  
  1069.         /* Redraw whole screen. */
  1070.         bufout(topline,1,SCRNL1);
  1071.  
  1072.         /* Restore the prompt line. */
  1073.         pmtzap();
  1074.     }
  1075.  
  1076.     TICKX("ed_sup");
  1077. }
  1078.  
  1079. /*
  1080.     Scroll screen down.  Topline will be new top line.
  1081. */
  1082. static void
  1083. ed_sdn(topline)
  1084. int topline;
  1085. {
  1086.     TRACEPB("ed_sdn", sl_lpout(); sl_iout(topline); sl_rpout());
  1087.  
  1088.     edtop = topline;
  1089.     if (hasins == TRUE) {
  1090.  
  1091.         /* Insert a line above line 1. */
  1092.         outxy(0, 1);
  1093.         outins();
  1094.  
  1095.         /* Redraw top line. */
  1096.         bufout(topline,1,1);
  1097.     }
  1098.     else if (hasdn == TRUE) {
  1099.  
  1100.         /* Hardware scroll. */
  1101.         outsdn();
  1102.  
  1103.         /* Redraw top line. */
  1104.         bufout(topline,1,1);
  1105.  
  1106.         /* Redraw the prompt line. */
  1107.         pmtzap();
  1108.     }
  1109.     else {
  1110.  
  1111.         /* Redraw whole screen. */
  1112.         bufout(topline,1,SCRNL1);
  1113.  
  1114.         /* Redraw the prompt line. */
  1115.         pmtzap();
  1116.     }
  1117.  
  1118.     TICKX("ed_sdn");
  1119. }
  1120.  
  1121. /*
  1122.     Insert one line below the current line on the screen.
  1123. */
  1124. static void
  1125. ed_ind(void)
  1126. {
  1127.     int y;
  1128.  
  1129.     TICKB("ed_ind");
  1130.  
  1131.     if (edatbot()) {
  1132.         ed_sup(bufln()-SCRNL2);
  1133.         outxy(edxpos(),SCRNL1);
  1134.     }
  1135.     else if (hasins == TRUE) {
  1136.         y = outy;
  1137.         outxy(0, y+1);
  1138.         outins();
  1139.         outxy(edxpos(), y+1);
  1140.     }
  1141.     else {
  1142.         y = outy;
  1143.         bufout(bufln(), y+1, SCRNL1-y);
  1144.         outxy(edxpos(), y+1);
  1145.     }
  1146.  
  1147.     TICKX("ed_ind");
  1148. }
  1149.  
  1150. /*
  1151.     Insert a line above the current line on the screen.
  1152. */
  1153. static void
  1154. ed_inu(void)
  1155. {
  1156.     int y;
  1157.  
  1158.     TICKB("ed_inu");
  1159.  
  1160.     if (hasins == TRUE) {
  1161.         y = outy;
  1162.         outins();
  1163.         outxy(edxpos(), y);
  1164.     }
  1165.     else if (edattop()) {
  1166.         ed_sdn(bufln());
  1167.         outxy(edxpos(), 1);
  1168.     }
  1169.     else {
  1170.         y = outy;
  1171.         bufout(bufln(), y, SCRNL - y);
  1172.         outxy(edxpos(), y);
  1173.     }
  1174.  
  1175.     TICKX("ed_inu");
  1176. }
  1177.  
  1178. /*
  1179.     Delete one line from the screen.
  1180. */
  1181. static void
  1182. ed_del(void)
  1183. {
  1184.     int y;
  1185.  
  1186.     TICKB("ed_del");
  1187.  
  1188.     /* Remember what line we are on. */
  1189.     y = outy;
  1190.  
  1191.     if (hasdel == TRUE) {
  1192.         outdel();
  1193.         bufout(bufln() + SCRNL1 - y, SCRNL1, 1);
  1194.     }
  1195.     else if (edattop()) {
  1196.         ed_sup(bufln());
  1197.         bufout(bufln() + SCRNL1 - y, SCRNL1, 1);
  1198.     }
  1199.     else {
  1200.         bufout(bufln(), y, SCRNL - y);
  1201.     }
  1202.  
  1203.     /* Set cursor to beginning of line. */
  1204.     outxy(0, y);
  1205.  
  1206.     TICKX("ed_del");
  1207. }
  1208.