home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / jove414s.zip / disp.c < prev    next >
C/C++ Source or Header  |  1991-07-07  |  35KB  |  1,473 lines

  1. /***************************************************************************
  2.  * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
  3.  * is provided to you without charge, and with no warranty.  You may give  *
  4.  * away copies of JOVE, including sources, provided that this notice is    *
  5.  * included in all the files.                                              *
  6.  ***************************************************************************/
  7.  
  8. #include "jove.h"
  9. #include "ctype.h"
  10. #include "termcap.h"
  11. #include "chars.h"
  12. #include "fp.h"
  13. #include "disp.h"
  14. #if (defined(IPROCS) || defined (OS2IPROCS))
  15. # include "iproc.h"
  16. #endif
  17.  
  18. #ifdef MAC
  19. # include "mac.h"
  20. #else
  21. # ifdef    STDARGS
  22. #  include <stdarg.h>
  23. # else
  24. #  include <varargs.h>
  25. # endif
  26. # include <sys/stat.h>
  27. #endif
  28.  
  29. #include <signal.h>
  30.  
  31. static void
  32. #ifdef ID_CHAR
  33.     DeTab proto((int, char *, char *, size_t, int)),
  34.     DelChar proto((int, int, int)),
  35.     InsChar proto((int, int, int, char *)),
  36. #endif
  37.     _fastcall DoIDline proto((int)),
  38.     _fastcall do_cl_eol proto((int)),
  39.     _fastcall ModeLine proto((Window *)),
  40.     GotoDot proto((void)),
  41.     _fastcall UpdLine proto((int)),
  42.     _fastcall UpdWindow proto((Window *, int));
  43.  
  44. #ifdef MSDOS
  45. extern void    _fastcall dobell proto ((int x));
  46. #else
  47. static void    _fastcall dobell proto((int x));
  48. #endif
  49.  
  50. static int
  51. #ifdef ID_CHAR
  52.     IDchar proto ((char *, int, int)),
  53.     NumSimilar proto ((char *, char *, int)),
  54.     IDcomp proto ((char *, char *, int)),
  55.     OkayDelete proto ((int, int, int)),
  56.     OkayInsert proto ((int, int)),
  57. #endif
  58.     _fastcall AddLines proto((int, int)),
  59.     _fastcall DelLines proto((int, int)),
  60.     _fastcall UntilEqual proto((int));
  61.  
  62.  
  63.  
  64. int    DisabledRedisplay = NO;
  65.  
  66. /* Kludge windows gets called by the routines that delete lines from the
  67.    buffer.  If the w->w_line or w->w_top are deleted and this procedure
  68.    is not called, the redisplay routine will barf. */
  69. /********************************************/
  70. void _fastcall
  71. ChkWindows(Line *line1, register  Line *line2)
  72. /********************************************/
  73. {
  74.     register  Window    *w = fwind;
  75.     register  Line    *lp;
  76.  
  77.     do {
  78.         for (lp = line1->l_next; lp != line2->l_next; lp = lp->l_next) {
  79.             if (lp == w->w_top)
  80.                 w->w_flags |= W_TOPGONE;
  81.             if (lp == w->w_line)
  82.                 w->w_flags |= W_CURGONE;
  83.         }
  84.         w = w->w_next;
  85.     } while (w != fwind);
  86. }
  87.  
  88. static int    RingBell;    /* So if we have a lot of errors ...
  89.                   ring the bell only ONCE */
  90.  
  91. /*********************/
  92. void redisplay (void)
  93. /*********************/
  94. {
  95.     void _fastcall screen_buffer_flush (void);
  96.     register  Window    *w = fwind;
  97.     void _fastcall Placur(int line, int col);
  98.     int    lineno,
  99.         done_ID = NO,
  100.         i;
  101.     register  struct scrimage    *des_p,
  102.                     *phys_p;
  103.  
  104.     if (DisabledRedisplay == YES)
  105.         return;
  106.     curwind->w_line = curwind->w_bufp->b_dot;
  107.     curwind->w_char = curwind->w_bufp->b_char;
  108. #ifdef MAC
  109.     InputPending = 0;
  110. #else
  111.     if ((InputPending = charp()) != '\0')    /* calls CheckEvent, which could */
  112.         return;    /* result in a call to rediplay(). We don't want that. */
  113. #endif
  114. #ifdef JOB_CONTROL
  115.     if (UpdFreq)
  116.         SigHold(SIGALRM);
  117. #endif
  118.     if (RingBell) {
  119.         dobell(1);
  120.         RingBell = 0;
  121.     }
  122.     AbortCnt = BufSize;        /* initialize this now */
  123.     if (UpdMesg)
  124.         DrawMesg(YES);
  125.  
  126.     for (lineno = 0, w = fwind; lineno < ILI; w = w->w_next) {
  127.         UpdWindow(w, lineno);
  128.         lineno += w->w_height;
  129.     }
  130.  
  131.     UpdModLine = 0;    /* Now that we've called update window, we can
  132.                assume that the modeline will be updated.  But
  133.                if while redrawing the modeline the user types
  134.                a character, ModeLine() is free to set this on
  135.                again so that the modeline will be fully drawn
  136.                at the next redisplay. */
  137.  
  138.     des_p = DesiredScreen;
  139.     phys_p = PhysScreen;
  140.     for (i = 0; i < ILI; i++, des_p++, phys_p++) {
  141.         if (!done_ID && (des_p->s_id != phys_p->s_id)) {
  142.             DoIDline(i);
  143.             done_ID = YES;
  144.         }
  145.         if ((des_p->s_flags & (DIRTY | L_MOD)) ||
  146.             (des_p->s_id != phys_p->s_id) ||
  147.             (des_p->s_vln != phys_p->s_vln) ||
  148.             (des_p->s_offset != phys_p->s_offset))
  149.             UpdLine(i);
  150.         if (InputPending)
  151.             goto ret;
  152.     }
  153.  
  154.     if (Asking) {
  155.         Placur(LI - 1, min(CO - 2, calc_pos(mesgbuf, Asking)));
  156.             /* Nice kludge */
  157.         flusho();
  158.         screen_buffer_flush();
  159.     } else
  160.         GotoDot();
  161. ret:
  162. #ifdef JOB_CONTROL
  163.     if (UpdFreq)
  164.         SigRelse(SIGALRM);
  165. #else
  166.     ;    /* yuck */
  167. #endif
  168. #ifdef MAC
  169.     if(Windchange) docontrols();
  170. #endif /* MAC */
  171. }
  172.  
  173. #ifndef IBMPC
  174. static void _fastcall
  175. dobell(n)
  176. int    n;
  177. {
  178.     void _fastcall screen_buffer_flush (void);
  179.     while (--n >= 0) {
  180. #ifndef MAC
  181.         if (VisBell && VB)
  182.             putstr(VB);
  183.         else
  184.             putpad(BL, 1);
  185. #else
  186.         SysBeep(5);
  187. #endif
  188.     }
  189.     flusho();
  190.     // screen_buffer_flush (); /* ? */
  191. }
  192. #endif /* IBMPC */
  193.  
  194. /* find_pos() returns the position on the line, that C_CHAR represents
  195.    in LINE */
  196.  
  197. /**********************************************/
  198. int _fastcall find_pos (Line *line, int c_char)
  199. /**********************************************/
  200. {
  201.     return calc_pos(lcontents(line), c_char);
  202. }
  203. /*******************************************************/
  204. int _fastcall calc_pos (char *lp, register  int c_char)
  205. /*******************************************************/
  206. {
  207.     register  int    pos = 0;
  208.     register  int    c;
  209.  
  210.  
  211.     while ((--c_char >= 0) && ((c = *lp++) & CHARMASK) != 0) {
  212.         if (c == '\t')
  213.             pos += (tabstop - (pos % tabstop));
  214.         else if (isctrl(c))
  215.             pos += 2;
  216.         else
  217.             pos += 1;
  218.     }
  219.     return pos;
  220. }
  221.  
  222. int    UpdModLine = 0,
  223.     UpdMesg = 0;
  224.  
  225. /******************************************/
  226. static void _fastcall DoIDline (int start)
  227. /******************************************/
  228. {
  229.     register  struct scrimage    *des_p = &DesiredScreen[start];
  230.     struct scrimage    *phys_p = &PhysScreen[start];
  231.     register  int    i,
  232.             j;
  233.  
  234.     /* Some changes have been made.  Try for insert or delete lines.
  235.        If either case has happened, Addlines and/or DelLines will do
  236.        necessary scrolling, also CONVERTING PhysScreen to account for the
  237.        physical changes.  The comparison continues from where the
  238.        insertion/deletion takes place; this doesn't happen very often,
  239.        usually it happens with more than one window with the same
  240.        buffer. */
  241.  
  242.     if (!CanScroll)
  243.         return;        /* We should never have been called! */
  244.  
  245.     for (i = start; i < ILI; i++, des_p++, phys_p++)
  246.         if (des_p->s_id != phys_p->s_id)
  247.             break;
  248.  
  249.     for (; i < ILI; i++) {
  250.         for (j = i + 1; j < ILI; j++) {
  251.             des_p = &DesiredScreen[j];
  252.             phys_p = &PhysScreen[j];
  253.             if (des_p->s_id != 0 && des_p->s_id == phys_p->s_id)
  254.                 break;
  255.             if (des_p->s_id == PhysScreen[i].s_id) {
  256.                 if (des_p->s_id == 0)
  257.                     continue;
  258.                 if (AddLines(i, j - i)) {
  259.                     DoIDline(j);
  260.                     return;
  261.                 }
  262.                 break;
  263.             }
  264.             if ((des_p = &DesiredScreen[i])->s_id == phys_p->s_id) {
  265.                 if (des_p->s_id == 0)
  266.                     continue;
  267.                 if (DelLines(i, j - i)) {
  268.                     DoIDline(i);
  269.                     return;
  270.                 }
  271.                 break;
  272.             }
  273.         }
  274.     }
  275. }
  276.  
  277. /* Make DesiredScreen reflect what the screen should look like when we are done
  278.    with the redisplay.  This deals with horizontal scrolling.  Also makes
  279.    sure the current line of the Window is in the window. */
  280.  
  281. int    ScrollAll = NO;
  282.  
  283. /******************************************************/
  284. static void _fastcall UpdWindow (Window *w, int start)
  285. /******************************************************/
  286. {
  287.     void _fastcall screen_buffer_flush (void);  /*DB*/
  288.     Line    *lp;
  289.     int    i,
  290.         upper,        /* top of window */
  291.         lower,        /* bottom of window */
  292.         strt_col,    /* starting print column of current line */
  293.         ntries = 0;    /* # of tries at updating window */
  294.     register  struct scrimage    *des_p,
  295.                     *phys_p;
  296.     Buffer    *bp = w->w_bufp;
  297.  
  298. retry:
  299.     if (w->w_flags & W_CURGONE) {
  300.         w->w_line = bp->b_dot;
  301.         w->w_char = bp->b_char;
  302.     }
  303.     if (w->w_flags & W_TOPGONE)
  304.         CentWind(w);    /* reset topline of screen */
  305.     w->w_flags &= ~(W_CURGONE | W_TOPGONE);
  306.  
  307.     /* make sure that the current line is in the window */
  308.     upper = start;
  309.     lower = upper + w->w_height - 1;    /* don't include modeline */
  310.     for (i = upper, lp = w->w_top; i < lower && lp != 0; lp = lp->l_next, i++)
  311.         if (lp == w->w_line)
  312.             break;
  313.     if (i == lower || lp == 0) {
  314.         ntries += 1;
  315.         if (ntries == 1) {
  316.             CalcWind(w);
  317.             goto retry;
  318.         } else if (ntries == 2) {
  319.             w->w_top = w->w_line = w->w_bufp->b_first;
  320.             writef("\rERROR in redisplay: I got hopelessly lost!");
  321.             dobell(2);
  322.             goto retry;
  323.         } else if (ntries == 3) {
  324.             writef("\n\rOops, still lost, quitting ...\r\n");
  325.             finish(1);
  326.         }
  327.     }
  328.  
  329.     /* first do some calculations for the current line */
  330.     {
  331.         int    diff = (w->w_flags & W_NUMLINES) ? 8 : 0,
  332.             end_col;
  333.  
  334.         strt_col = (ScrollAll == YES) ? w->w_LRscroll :
  335.                PhysScreen[i].s_offset;
  336.         end_col = strt_col + (CO - 2) - diff;
  337.         /* Right now we are displaying from strt_col to
  338.            end_col of the buffer line.  These are PRINT
  339.            columns, not actual characters. */
  340.         w->w_dotcol = find_pos(w->w_line, w->w_char);
  341.         /* if the new dotcol is out of range, reselect
  342.            a horizontal window */
  343.         if ((PhysScreen[i].s_offset == -1) ||
  344.             (w->w_dotcol < strt_col) ||
  345.             (w->w_dotcol >= end_col)) {
  346.             if (w->w_dotcol < ((CO - 2) - diff))
  347.                 strt_col = 0;
  348.             else
  349.                 strt_col = w->w_dotcol - (CO / 2);
  350.             if (ScrollAll == YES) {
  351.                 if (w->w_LRscroll != strt_col)
  352.                     UpdModLine = YES;
  353.                 w->w_LRscroll = strt_col;
  354.             }
  355.         }
  356.         w->w_dotline = i;
  357.         w->w_dotcol += diff;
  358.     }
  359.  
  360.     des_p = &DesiredScreen[upper];
  361.     phys_p = &PhysScreen[upper];
  362.     for (i = upper, lp = w->w_top; lp != 0 && i < lower; i++, des_p++, phys_p++, lp = lp->l_next) {
  363.         des_p->s_window = w;
  364.         des_p->s_lp = lp;
  365.         des_p->s_id = lp->l_dline & ~DIRTY;
  366.         des_p->s_flags = isdirty(lp) ? L_MOD : 0;
  367.         if (w->w_flags & W_NUMLINES)
  368.             des_p->s_vln = w->w_topnum + (i - upper);
  369.         else
  370.             des_p->s_vln = 0;
  371.  
  372.         if (lp == w->w_line)
  373.             des_p->s_offset = strt_col;
  374.         else
  375.             des_p->s_offset = w->w_LRscroll;
  376.     }
  377.  
  378.     /* Is structure assignment faster than copy each field separately? */
  379.     if (i < lower) {
  380.         static const struct scrimage    dirty_plate = { 0, DIRTY, 0, 0, 0, 0 },
  381.                     clean_plate = { 0, 0, 0, 0, 0, 0 };
  382.  
  383.         for (; i < lower; i++, des_p++, phys_p++)
  384.             if (phys_p->s_id != 0)
  385.                 *des_p = dirty_plate;
  386.             else
  387.                 *des_p = clean_plate;
  388.     }
  389.  
  390.     des_p->s_window = w;
  391.     des_p->s_flags = 0;
  392.     if (((des_p->s_id = (int) w->w_bufp) != phys_p->s_id) || UpdModLine)
  393.         des_p->s_flags = MODELINE | DIRTY;
  394. #ifdef MAC
  395.     if (UpdModLine)
  396.         Modechange = 1;
  397.     if (w == curwind && w->w_control)
  398.         SetScrollBar(w->w_control);
  399. #endif
  400.     //screen_buffer_flush();    /* ? */
  401. }
  402.  
  403. /* Write whatever is in mesgbuf (maybe we are Asking, or just printed
  404.    a message).  Turns off the UpdateMesg line flag. */
  405.  
  406. /***************************************/
  407. void _fastcall DrawMesg (int abortable)
  408. /***************************************/
  409. {
  410.     void _fastcall screen_buffer_flush (void);  /*DB*/
  411.     void _fastcall flush_message_line (void);
  412.  
  413. #ifndef MAC        /* same reason as in redisplay() */
  414.     if (charp())
  415.         return;
  416. #endif
  417.     i_set(ILI, 0);
  418.     if (swrite(mesgbuf, NO, abortable)) {
  419.         cl_eol();
  420.         UpdMesg = 0;
  421.     }
  422.     flusho();
  423.     flush_message_line ();
  424. }
  425.  
  426. /* Goto the current position in the current window.  Presumably redisplay()
  427.    has already been called, and curwind->{w_dotline,w_dotcol} have been set
  428.    correctly. */
  429.  
  430. /**************************/
  431. static void GotoDot (void)
  432. /**************************/
  433. {
  434.     void _fastcall screen_buffer_flush (void);
  435.     void _fastcall Placur(int line, int col);
  436.     if (InputPending)
  437.         return;
  438.     Placur(curwind->w_dotline, curwind->w_dotcol -
  439.                 PhysScreen[curwind->w_dotline].s_offset);
  440.     flusho();
  441.     screen_buffer_flush (); /* ? */
  442. }
  443.  
  444. /*****************************************************/
  445. static int _fastcall UntilEqual (register  int start)
  446. /*****************************************************/
  447. {
  448.     register  struct scrimage    *des_p = &DesiredScreen[start],
  449.                     *phys_p = &PhysScreen[start];
  450.  
  451.     while ((start < ILI) && (des_p->s_id != phys_p->s_id)) {
  452.         des_p += 1;
  453.         phys_p += 1;
  454.         start += 1;
  455.     }
  456.  
  457.     return start;
  458. }
  459.  
  460. /* Calls the routine to do the physical changes, and changes PhysScreen to
  461.    reflect those changes. */
  462.  
  463. /********************************************************/
  464. static int _fastcall AddLines (register  int at, int num)
  465. /********************************************************/
  466. {
  467.     register  int    i;
  468.     int    bottom = UntilEqual(at + num);
  469.  
  470.     if (num == 0 || num >= ((bottom - 1) - at))
  471.         return NO;                /* we did nothing */
  472.     v_ins_line(num, at, bottom - 1);
  473.  
  474.     /* Now change PhysScreen to account for the physical change. */
  475.  
  476.     for (i = bottom - 1; i - num >= at; i--)
  477.         PhysScreen[i] = PhysScreen[i - num];
  478.     for (i = 0; i < num; i++)
  479.         PhysScreen[at + i].s_id = 0;
  480.     return YES;                    /* we did something */
  481. }
  482.  
  483. /******************************************************************/
  484. static int _fastcall DelLines (register  int at, register  int num)
  485. /******************************************************************/
  486. {
  487.     register  int    i;
  488.     int    bottom = UntilEqual(at + num);
  489.  
  490.     if (num == 0 || num >= ((bottom - 1) - at))
  491.         return NO;
  492.     v_del_line(num, at, bottom - 1);
  493.  
  494.     for (i = at; num + i < bottom; i++)
  495.         PhysScreen[i] = PhysScreen[num + i];
  496.     for (i = bottom - num; i < bottom; i++)
  497.         PhysScreen[i].s_id = 0;
  498.     return YES;
  499. }
  500.  
  501. /* Update line linenum in window w.  Only set PhysScreen to DesiredScreen
  502.    if the swrite or cl_eol works, that is nothing is interupted by
  503.    characters typed. */
  504.  
  505. /****************************************************/
  506. static  void _fastcall UpdLine (register int linenum)
  507. /****************************************************/
  508. {
  509.     void _fastcall screen_buffer_flush (void);
  510.     register  struct scrimage    *des_p = &DesiredScreen[linenum];
  511.     register Window    *w = des_p->s_window;
  512.  
  513.     i_set(linenum, 0);
  514.     if (des_p->s_flags & MODELINE)
  515.         ModeLine(w);
  516.     else if (des_p->s_id) {
  517.         des_p->s_lp->l_dline &= ~DIRTY;
  518.         des_p->s_flags &= ~(DIRTY | L_MOD);
  519. #ifdef ID_CHAR
  520.         if (!UseIC && (w->w_flags & W_NUMLINES))
  521. #else
  522.         if (w->w_flags & W_NUMLINES)
  523. #endif
  524.             (void) swrite(sprint("%6d  ", des_p->s_vln), NO, YES);
  525.  
  526. #ifdef ID_CHAR
  527.         if (UseIC) {
  528.             char    outbuf[MAXCOLS],
  529.                 *lptr;
  530.             int    fromcol = (w->w_flags & W_NUMLINES) ? 8 : 0;
  531.  
  532.             if (w->w_flags & W_NUMLINES)
  533.                 swritef(outbuf, "%6d  ", des_p->s_vln);
  534.             lptr = lcontents(des_p->s_lp);
  535.             DeTab(des_p->s_offset, lptr, outbuf + fromcol,
  536.                 (sizeof outbuf) - 1 - fromcol,
  537.                 des_p->s_window->w_flags & W_VISSPACE);
  538.             if (IDchar(outbuf, linenum, 0))
  539.                 PhysScreen[linenum] = *des_p;
  540.             else if (i_set(linenum, 0), swrite(outbuf, NO, YES))
  541.                 do_cl_eol(linenum);
  542.             else
  543.                 PhysScreen[linenum].s_id = -1;
  544.         } else
  545. #endif /* ID_CHAR */
  546.             if (BufSwrite(linenum))
  547.             do_cl_eol(linenum);
  548.         else
  549.             PhysScreen[linenum].s_id = -1;
  550.     } else if (PhysScreen[linenum].s_id)    /* not the same ... make sure */
  551.         do_cl_eol(linenum);
  552. }
  553.  
  554. /********************************************************/
  555. static void _fastcall do_cl_eol (register  int    linenum)
  556. /********************************************************/
  557. {
  558.     cl_eol();
  559.     PhysScreen[linenum] = DesiredScreen[linenum];
  560. }
  561.  
  562. #ifdef ID_CHAR
  563.  
  564. /* From here to the end of the file is code that tries to utilize the
  565.    insert/delete character feature on some terminals.  It is very confusing
  566.    and not so well written code, AND there is a lot of it.  You may want
  567.    to use the space for something else. */
  568.  
  569. int    IN_INSmode = 0;
  570.  
  571. int    UseIC;
  572.  
  573. int    DClen,
  574.     MDClen,
  575.     IClen,
  576.     MIClen,
  577.     IMlen,
  578.     CElen;
  579.  
  580. /*************************/
  581. void disp_opt_init (void)
  582. /*************************/
  583. {
  584.     DClen = DC ? strlen(DC) : 0;
  585.     MDClen = M_DC ? strlen(M_DC) : 9999;
  586.     IClen = IC ? strlen(IC) : 0;
  587.     MIClen = M_IC ? strlen(M_IC) : 9999;
  588.     IMlen = IM ? strlen(IM) : 0;
  589.     CElen = CE ? strlen(CE) : 0;
  590.  
  591.     UseIC = (IC || IM || M_IC);
  592. }
  593.  
  594. /*********************/
  595. void INSmode (int on)
  596. /*********************/
  597. {
  598.     if (on && !IN_INSmode) {
  599.         putpad(IM, 1);
  600.         IN_INSmode = YES;
  601.     } else if (!on && IN_INSmode) {
  602.         putpad(EI, 1);
  603.         IN_INSmode = NO;
  604.     }
  605. }
  606.  
  607. /******************************************************************/
  608. static void DeTab(int s_offset, register  char *buf, char *outbuf,
  609.           size_t limit, int visspace)
  610. /******************************************************************/
  611. {
  612.     register  char    *phys_p = outbuf,
  613.             c;
  614.     register  int    pos = 0;
  615.     char        *limitp = &outbuf[limit];
  616.  
  617. #define OkayOut(ch)    { \
  618.     if ((pos++ >= s_offset) && (phys_p < limitp)) \
  619.         *phys_p++ = (ch); \
  620. }
  621.  
  622.     while ((c = *buf++) != '\0') {
  623.         if (c == '\t') {
  624.             int    nchars = (tabstop - (pos % tabstop));
  625.  
  626.             if (visspace) {
  627.                 OkayOut('>');
  628.                 nchars -= 1;
  629.             }
  630.             while (--nchars >= 0)
  631.                 OkayOut(' ');
  632.  
  633.         } else if (isctrl(c)) {
  634.             OkayOut('^');
  635.             OkayOut(c == 0177 ? '?' : c + '@');
  636.         } else {
  637.             if (visspace && c == ' ')
  638.                 c = '_';
  639.             OkayOut(c);
  640.         }
  641.         if (pos - s_offset >= CO) {
  642.             phys_p = &outbuf[CO - 1];
  643.             *phys_p++ = '!';
  644.             break;
  645.         }
  646.     }
  647.     *phys_p = 0;
  648.  
  649. #undef    OkayOut
  650. }
  651.  
  652. /* ID character routines full of special cases and other fun stuff like that.
  653.    It actually works though ...
  654.  
  655.     Returns Non-Zero if you are finished (no differences left). */
  656.  
  657. /************************************************************/
  658. static int IDchar (register  char *new, int lineno, int col)
  659. /************************************************************/
  660. {
  661.     register  int    i;
  662.     int    j,
  663.         oldlen,
  664.         NumSaved;
  665.     register  struct screenline    *sline = &Screen[lineno];
  666.  
  667.     oldlen = sline->s_length - sline->s_line;
  668.  
  669.     for (i = col; i < oldlen && new[i] != 0; i++)
  670.         if (sline->s_line[i] != new[i])
  671.             break;
  672.     if (new[i] == 0 || i == oldlen)
  673.         return (new[i] == 0 && i == oldlen);
  674.  
  675.     for (j = i + 1; j < oldlen && new[j]; j++) {
  676.         if (new[j] == sline->s_line[i]) {
  677.             NumSaved = IDcomp(new + j, sline->s_line + i,
  678.                     (int)strlen(new)) + NumSimilar(new + i,
  679.                         sline->s_line + i, j - i);
  680.             if (OkayInsert(NumSaved, j - i)) {
  681.                 InsChar(lineno, i, j - i, new);
  682.                 return(IDchar(new, lineno, j));
  683.             }
  684.         }
  685.     }
  686.  
  687.     for (j = i + 1; j < oldlen && new[i]; j++) {
  688.         if (new[i] == sline->s_line[j]) {
  689.             NumSaved = IDcomp(new + i, sline->s_line + j,
  690.                     oldlen - j);
  691.             if (OkayDelete(NumSaved, j - i, new[oldlen] == 0)) {
  692.                 DelChar(lineno, i, j - i);
  693.                 return(IDchar(new, lineno, j));
  694.             }
  695.         }
  696.     }
  697.     return 0;
  698. }
  699.  
  700. /******************************************************************/
  701. static int NumSimilar(register  char *s, register  char    *t, int n)
  702. /******************************************************************/
  703. {
  704.     register  int    num = 0;
  705.  
  706.     while (n--)
  707.         if (*s++ == *t++)
  708.             num += 1;
  709.     return num;
  710. }
  711.  
  712. /******************************************************************/
  713. static int IDcomp(register  char *s, register  char *t, int len)
  714. /******************************************************************/
  715. {
  716.     register  int    i;
  717.     int    num = 0,
  718.         nonspace = 0;
  719.     char    c;
  720.  
  721.     for (i = 0; i < len; i++) {
  722.         if ((c = *s++) != *t++)
  723.             break;
  724.         if (c != ' ')
  725.             nonspace++;
  726.         if (nonspace)
  727.             num += 1;
  728.     }
  729.  
  730.     return num;
  731. }
  732.  
  733. /***********************************************************/
  734. static int OkayDelete (int Saved, int num, int samelength)
  735. /***********************************************************/
  736. {
  737.     /* If the old and the new are the same length, then we don't
  738.      * have to clear to end of line.  We take that into consideration.
  739.      */
  740.     return ((Saved + (!samelength ? CElen : 0))
  741.         > min(MDClen, DClen * num));
  742. }
  743.  
  744. /******************************************/
  745. static int OkayInsert (int Saved, int num)
  746. /******************************************/
  747. {
  748.     register  int    n = 0;
  749.  
  750.     if (IC)        /* Per character prefixes */
  751.         n = min(num * IClen, MIClen);
  752.  
  753.     if (IM && !IN_INSmode) {
  754.         /* Good terminal.  Fewer characters in this case */
  755.         n += IMlen;
  756.     }
  757.  
  758.     n += num;    /* The characters themselves */
  759.  
  760.     return Saved > n;
  761. }
  762.  
  763. /**************************************************/
  764. static void DelChar (int lineno, int col, int num)
  765. /**************************************************/
  766. {
  767.     void _fastcall Placur(int line, int col);
  768.     register  char    *from,
  769.             *to;
  770.     register  int    i;
  771.     struct screenline *sp = (&Screen[lineno]);
  772.  
  773.     Placur(lineno, col);
  774.     if (M_DC && num > 1) {
  775.         putargpad(M_DC, num, num);
  776.     } else {
  777.         for (i = num; --i >= 0; )
  778.             putpad(DC, 1);
  779.     }
  780.  
  781.     to = sp->s_line + col;
  782.     from = to + num;
  783.  
  784.     byte_copy(from, to, (size_t) (sp->s_length - from + 1));
  785.     clrline(sp->s_length - num, sp->s_length);
  786.     sp->s_length -= num;
  787. }
  788.  
  789. /**************************************************************/
  790. static void InsChar (int lineno, int col, int num, char *new)
  791. /**************************************************************/
  792. {
  793.     void _fastcall Placur(int line, int col);
  794.     register  char    *sp1,
  795.                 *sp2,    /* To push over the array. */
  796.                 *sp3;    /* Last character to push over. */
  797.     int    i;
  798.  
  799.     i_set(lineno, 0);
  800.     sp2 = Curline->s_length + num;
  801.  
  802.     if (sp2 >= cursend) {
  803.         i_set(lineno, CO - num - 1);
  804.         cl_eol();
  805.         sp2 = cursend - 1;
  806.     }
  807.     Curline->s_length = sp2;
  808.     sp1 = sp2 - num;
  809.     sp3 = Curline->s_line + col;
  810.  
  811.     while (sp1 >= sp3)
  812.         *sp2-- = *sp1--;
  813.  
  814.     new += col;
  815.     byte_copy(new, sp3, (size_t) num);
  816.     /* The internal screen is correct, and now we have to do
  817.        the physical stuff. */
  818.  
  819.     Placur(lineno, col);
  820.     if (IM) {
  821.         if (!IN_INSmode)
  822.             INSmode(1);
  823.     } else if (M_IC && num > 1) {
  824.         putargpad(M_IC, num, num);
  825.     } else if (IC) {
  826.         for (i = 0; i < num; i++)
  827.             putpad(IC, 1);
  828.     }
  829.     for (i = 0; i < num; i++) {
  830.         jputchar(new[i]);
  831.         if (IN_INSmode)
  832.             putpad(IP, 1);
  833.     }
  834.     CapCol += num;
  835. }
  836.  
  837. #endif /* ID_CHAR */
  838.  
  839. #ifdef UNIX        /* obviously ... no mail today if not Unix*/
  840.  
  841. /* chkmail() returns nonzero if there is new mail since the
  842.    last time we checked. */
  843.  
  844. char    Mailbox[FILESIZE];    /* initialized in main */
  845. int    MailInt = 60;        /* check no more often than 60 seconds */
  846. #ifdef BIFF
  847. int    BiffChk = NO;        /* whether to turn off biff while in JOVE */
  848. #endif
  849.  
  850. /***********************/
  851. int chkmail (int force)
  852. /***********************/
  853. {
  854.     time_t    now;
  855.     static int    state = NO;    /* assume unknown */
  856.     static time_t    last_chk = 0,
  857.             mbox_time = 0;
  858.     struct stat    stbuf;
  859.  
  860.     if (MailInt == 0)
  861.         return NO;
  862.     time(&now);
  863.     if ((force == NO) && (now < last_chk + MailInt))
  864.         return state;
  865.     last_chk = now;
  866.     if (stat(Mailbox, &stbuf) < 0) {
  867.         state = NO;        /* no mail */
  868.         return NO;
  869.     }
  870.     if (((stbuf.st_atime > stbuf.st_mtime) &&
  871.          (stbuf.st_atime > mbox_time)) ||
  872.         (stbuf.st_size == 0)) {
  873.         mbox_time = stbuf.st_atime;
  874.         state = NO;
  875.     } else if (stbuf.st_mtime > mbox_time) {
  876.         if (mbox_time > 0)
  877.             dobell(2);        /* announce the change */
  878.         mbox_time = stbuf.st_mtime;
  879.         state = YES;
  880.     }
  881.     return state;
  882. }
  883.  
  884. #endif /* UNIX */
  885.  
  886. /* Print the mode line. */
  887.  
  888. static char    *mode_p,
  889.         *mend_p;
  890. int    BriteMode = 1;        /* modeline should standout */
  891.  
  892. /************************************************/
  893. static void mode_app (register  const char *str)
  894. /************************************************/
  895. {
  896.     while ((mode_p < mend_p) && (*mode_p++ = *str++)!='\0')
  897.         ;
  898.     mode_p -= 1;    /* back over the null */
  899. }
  900.  
  901. char    ModeFmt[120] = "%3c %w %[%sJOVE (%M)   Buffer: %b  \"%f\" %]%s%m*- %((%t)%s%)%e";
  902.  
  903. /*****************************************************/
  904. static  void _fastcall ModeLine (register  Window *w)
  905. /*****************************************************/
  906. {
  907.     void _fastcall screen_buffer_flush (void);
  908.     void  _fastcall SO_on(void);
  909.     void _fastcall SO_off(void);
  910.     int    n,
  911.         ign_some = NO,
  912.         glue = 0;
  913.     char    line[MAXCOLS],
  914.         *fmt = ModeFmt,
  915.         fillc,
  916.         c;
  917.     register  Buffer    *thisbuf = w->w_bufp;
  918.     register  Buffer *bp;
  919.  
  920.     mode_p = line;
  921.     mend_p = &line[(sizeof line) - 1];
  922.  
  923. #ifdef IBMPC
  924.     /* very subtle - don't mess up attributes too much */
  925.     fillc = '-';
  926. #else /* !IBMPC */
  927. #  ifdef MAC
  928.     fillc = '_';    /* looks better on a Mac */
  929. #  else /* !MAC */
  930.     if (SO == 0)
  931.         BriteMode = 0;
  932.     fillc = BriteMode ? ' ' : '-';
  933. #  endif /* !MAC */
  934. #endif /* !IBMPC */
  935.  
  936.     while ((c = *fmt++)!='\0' && mode_p<mend_p) {
  937.         if (c != '%') {
  938.             if (c == '\\')
  939.                 if ((c = *fmt++) == '\0')
  940.                     break;
  941.             if (!ign_some)
  942.                 *mode_p++ = c;
  943.             continue;
  944.         }
  945.         if ((c = *fmt++) == '\0')    /* char after the '%' */
  946.             break;
  947.         if (ign_some && c != ')')
  948.             continue;
  949.         n = 1;
  950.         if (c >= '0' && c <= '9') {
  951.             n = 0;
  952.             while (c >= '0' && c <= '9') {
  953.                 n = n * 10 + (c - '0');
  954.                 c = *fmt++;
  955.             }
  956.             if (c == '\0')
  957.                 break;
  958.         }
  959.         switch (c) {
  960.         case '(':
  961.             if (w->w_next != fwind)    /* Not bottom window. */
  962.                 ign_some = YES;
  963.             break;
  964.  
  965.         case ')':
  966.             ign_some = NO;
  967.             break;
  968.  
  969.         case '[':
  970.         case ']':
  971.             for (n=RecDepth; n>0 && mode_p<mend_p; n--)
  972.                 *mode_p++ = c;
  973.             break;
  974.  
  975. #ifdef UNIX
  976.         case 'C':    /* check mail here */
  977.             if (chkmail(NO) == YES)
  978.                 mode_app("[New mail]");
  979.             break;
  980.  
  981. #endif /* UNIX */
  982.  
  983.         case 'M':
  984.             {
  985.             static const char    *const mmodes[] = {
  986.                 "Fundamental ",
  987.                 "Text ",
  988.                 "C ",
  989. #ifdef LISP
  990.                 "Lisp ",
  991. #endif
  992.                 0
  993.             };
  994.  
  995.             mode_app(mmodes[thisbuf->b_major]);
  996.  
  997.             if (BufMinorMode(thisbuf, Fill))
  998.                 mode_app("Fill ");
  999.             if (BufMinorMode(thisbuf, Abbrev))
  1000.                 mode_app("Abbrev ");
  1001.             if (BufMinorMode(thisbuf, OverWrite))
  1002.                 mode_app("OvrWt ");
  1003.             if (BufMinorMode(thisbuf, Indent))
  1004.                 mode_app("AI ");
  1005.             if (BufMinorMode(thisbuf, ReadOnly))
  1006.                 mode_app("RO ");
  1007.             if (InMacDefine)
  1008.                 mode_app("Def ");
  1009.             mode_p -= 1;    /* Back over the extra space. */
  1010.             break;
  1011.             }
  1012.  
  1013.         case 'c':
  1014.             while (--n>=0 && mode_p<mend_p)
  1015.                 *mode_p++ = fillc;
  1016.             break;
  1017.  
  1018.         case 'd':    /* print working directory */
  1019.             mode_app(pr_name(pwd(), YES));
  1020.             break;
  1021.  
  1022.         case 'e':    /* stretchable glue */
  1023.             *mode_p++ = '\0';    /* glue marker */
  1024.             glue++;
  1025.             break;
  1026.  
  1027.         case 'b':
  1028.             mode_app(thisbuf->b_name);
  1029.             break;
  1030.  
  1031.         case 'f':
  1032.         case 'F':
  1033.             if (thisbuf->b_fname == 0)
  1034.                 mode_app("[No file]");
  1035.             else {
  1036.                 if (c == 'f')
  1037.                     mode_app(pr_name(thisbuf->b_fname, YES));
  1038.                 else
  1039.                     mode_app(basename(thisbuf->b_fname));
  1040.             }
  1041.             break;
  1042.  
  1043. #ifdef LOAD_AV
  1044.         case 'l':
  1045.             {
  1046.             double    theavg;
  1047.             char    minibuf[10];
  1048.  
  1049.             get_la(&theavg);
  1050.             theavg += .005;    /* round to nearest .01 */
  1051.             swritef(minibuf, "%d.%02d",
  1052.                    (int) theavg,
  1053.                    (int)((theavg - (int) theavg) * 100));
  1054.             mode_app(minibuf);
  1055.             break;
  1056.             }
  1057. #endif
  1058.  
  1059.         case 'm':
  1060.             {
  1061.             char    yea = (*fmt == '\0') ? '*' : *fmt++;
  1062.             char    nay = (*fmt == '\0') ? ' ' : *fmt++;
  1063.  
  1064.             *mode_p++ = IsModified(w->w_bufp) ? yea : nay;
  1065.             break;
  1066.             }
  1067.  
  1068.         case 'n':
  1069.             {
  1070.             char    tmp[16];
  1071.             for (bp = world, n = 1; bp != 0; bp = bp->b_next, n++)
  1072.                 if (bp == thisbuf)
  1073.                     break;
  1074.  
  1075.             swritef(tmp, "%d", n);
  1076.             mode_app(tmp);
  1077.             break;
  1078.             }
  1079.  
  1080. #if defined (IPROCS) || defined (OS2IPROCS)
  1081.         case 'p':
  1082.             if (thisbuf->b_type == B_PROCESS) {
  1083.                 char    tmp[40];
  1084.                 Process    *p = thisbuf->b_process;
  1085.  
  1086.                 swritef(tmp, "(%s%s)",
  1087.                     ((p == 0 || p->p_dbx_mode == NO)
  1088.                      ? "" : "DBX "),
  1089.                     ((p == 0) ? "No process" :
  1090.                      pstate(p)));
  1091.                 mode_app(tmp);
  1092.             }
  1093.             break;
  1094. #endif
  1095.  
  1096.         case 's':
  1097.             if (mode_p[-1] != ' ')
  1098.                 *mode_p++ = ' ';
  1099.             break;
  1100.  
  1101.         case 't':
  1102.             {
  1103.             char    timestr[12];
  1104.  
  1105.             mode_app(get_time((time_t *) 0, timestr, 11, 16));
  1106.             break;
  1107.             }
  1108.  
  1109.         case 'w':
  1110.             if (w->w_LRscroll > 0)
  1111.                 mode_app(">");
  1112.             break;
  1113.         }
  1114.     }
  1115.  
  1116.     /* Glue (Knuth's term) is a field that expands to fill
  1117.      * any leftover space.  Multiple glue fields compete
  1118.      * on an equal basis.  This is a generalization of a
  1119.      * mechanism to allow centring and right-justification.
  1120.      * The original meaning of %e (fill the rest of the
  1121.      * line) has also been generalized.  %e can now
  1122.      * meaningfully be used 0 or more times.
  1123.      */
  1124.  
  1125.     if  (glue) {
  1126.         /* 2 space pad plus padding for magic cookies */
  1127.         register  char    *to = &line[CO - 2 - (2 * SG)],
  1128.                 *from = mode_p;
  1129.  
  1130.         if (to < from)
  1131.             to = from;
  1132.         mode_p = to;
  1133.         while (from != line) {
  1134.             if ((*--to = *--from) == '\0') {
  1135.                 register  int    portion = (to-from) / glue;
  1136.  
  1137.                 glue--;
  1138.                 *to = fillc;
  1139.                 while (--portion >= 0)
  1140.                     *--to = fillc;
  1141.             }
  1142.         }
  1143.     }
  1144.  
  1145.     *mode_p = 0;
  1146.  
  1147.     /* Highlight mode line. */
  1148.     if (BriteMode) {
  1149. #ifdef ID_CHAR
  1150.         if (IN_INSmode)
  1151.             INSmode(0);
  1152. #endif
  1153.         SO_on();
  1154.     }
  1155.     if (swrite(line, BriteMode, YES))
  1156.         do_cl_eol(i_line);
  1157.     else
  1158.         UpdModLine = 1;
  1159.     if (BriteMode)
  1160.         SO_off();
  1161. }
  1162.  
  1163. /**************************************************************/
  1164. static void _fastcall v_clear (register  int line1, int line2)
  1165. /**************************************************************/
  1166. {
  1167.     register  struct scrimage    *phys_p, *des_p;
  1168.  
  1169.     phys_p = &PhysScreen[line1];
  1170.     des_p = &DesiredScreen[line1];
  1171.  
  1172.     while (line1 <= line2) {
  1173.         i_set(line1, 0);
  1174.         cl_eol();
  1175.         phys_p->s_id = des_p->s_id = 0;
  1176.         phys_p += 1;
  1177.         des_p += 1;
  1178.         line1 += 1;
  1179.     }
  1180. }
  1181.  
  1182. /* This tries to place the current line of the current window in the
  1183.    center of the window, OR to place it at the arg'th line of the window.
  1184.    This also causes the horizontal position of the line to be centered,
  1185.    if the line needs scrolling, or moved all the way back to the left,
  1186.    if that's possible. */
  1187. /*************************/
  1188. void RedrawDisplay (void)
  1189. /*************************/
  1190. {
  1191.     int    line;
  1192.     Line    *newtop = prev_line((curwind->w_line = curline), is_an_arg() ?
  1193.                 arg_value() : HALF(curwind));
  1194.  
  1195.     if ((line = in_window(curwind, curwind->w_line)) != -1)
  1196.         PhysScreen[line].s_offset = -1;
  1197.     if (newtop == curwind->w_top)
  1198.         v_clear(FLine(curwind), FLine(curwind) + SIZE(curwind));
  1199.     else
  1200.         SetTop(curwind, newtop);
  1201. }
  1202.  
  1203. /***********************/
  1204. void ClAndRedraw (void)
  1205. /***********************/
  1206. {
  1207.     cl_scr(YES);
  1208. }
  1209.  
  1210. /********************/
  1211. void NextPage (void)
  1212. /********************/
  1213. {
  1214.     Line    *newline;
  1215.  
  1216.     if (Asking)
  1217.         return;
  1218.     if (arg_value() < 0) {
  1219.         negate_arg_value();
  1220.         PrevPage();
  1221.         return;
  1222.     }
  1223.     if (arg_type() == YES)
  1224.         UpScroll();
  1225.     else {
  1226.         if (in_window(curwind, curwind->w_bufp->b_last) != -1) {
  1227.             rbell();
  1228.             return;
  1229.         }
  1230.         newline = next_line(curwind->w_top, max(1, SIZE(curwind) - 1));
  1231.         SetTop(curwind, curwind->w_line = newline);
  1232.         if (curwind->w_bufp == curbuf)
  1233.             SetLine(newline);
  1234.     }
  1235. }
  1236.  
  1237. #ifdef MSDOS        /* kg */
  1238.  
  1239. /************************/
  1240. void PageScrollUp (void)
  1241. /************************/
  1242. {
  1243.     int i, n;
  1244.  
  1245.     n = max(1, SIZE(curwind) - 1);
  1246.     for (i=0; i<n; i++) {
  1247.         UpScroll();
  1248.         redisplay();
  1249.     }
  1250. }
  1251.  
  1252. /**************************/
  1253. void PageScrollDown (void)
  1254. /**************************/
  1255. {
  1256.     int i, n;
  1257.  
  1258.     n = max(1, SIZE(curwind) - 1);
  1259.     for (i=0; i<n; i++) {
  1260.         DownScroll();
  1261.         redisplay();
  1262.     }
  1263. }
  1264. #endif /* MSDOS */
  1265.  
  1266. /********************/
  1267. void PrevPage (void)
  1268. /********************/
  1269. {
  1270.     Line    *newline;
  1271.  
  1272.     if (Asking)
  1273.         return;
  1274.     if (arg_value() < 0) {
  1275.         negate_arg_value();
  1276.         NextPage();
  1277.         return;
  1278.     }
  1279.     if (arg_type() == YES)
  1280.         DownScroll();
  1281.     else {
  1282.         newline = prev_line(curwind->w_top, max(1, SIZE(curwind) - 1));
  1283.         SetTop(curwind, curwind->w_line = newline);
  1284.         if (curwind->w_bufp == curbuf)
  1285.             SetLine(newline);
  1286.     }
  1287. }
  1288.  
  1289. /********************/
  1290. void UpScroll (void)
  1291. /********************/
  1292. {
  1293.     SetTop(curwind, next_line(curwind->w_top, arg_value()));
  1294.     if ((curwind->w_bufp == curbuf) &&
  1295.         (in_window(curwind, curline) == -1))
  1296.         SetLine(curwind->w_top);
  1297. }
  1298.  
  1299. /**********************/
  1300. void DownScroll (void)
  1301. /**********************/
  1302. {
  1303.     SetTop(curwind, prev_line(curwind->w_top, arg_value()));
  1304.     if ((curwind->w_bufp == curbuf) &&
  1305.         (in_window(curwind, curline) == -1))
  1306.         SetLine(curwind->w_top);
  1307. }
  1308.  
  1309. int    VisBell = NO;
  1310.  
  1311. /*****************/
  1312. void rbell (void)
  1313. /*****************/
  1314. {
  1315.     RingBell = YES;
  1316. }
  1317.  
  1318. /* Message prints the null terminated string onto the bottom line of the
  1319.    terminal. */
  1320.  
  1321. /*********************************/
  1322. void _fastcall message(char *str)
  1323. /*********************************/
  1324. {
  1325.     if (InJoverc)
  1326.         return;
  1327.     UpdMesg = YES;
  1328.     errormsg = NO;
  1329.     if (str != mesgbuf)
  1330.         null_ncpy(mesgbuf, str, (sizeof mesgbuf) - 1);
  1331. }
  1332.  
  1333. /* End of Window */
  1334.  
  1335. /***************/
  1336. void Eow (void)
  1337. /***************/
  1338. {
  1339.     if (Asking)
  1340.         return;
  1341.     SetLine(next_line(curwind->w_top, SIZE(curwind) - 1 -
  1342.             min(SIZE(curwind) - 1, arg_value() - 1)));
  1343.     if (!is_an_arg())
  1344.         Eol();
  1345. }
  1346.  
  1347. /* Beginning of Window */
  1348.  
  1349. /***************/
  1350. void Bow (void)
  1351. /***************/
  1352. {
  1353.     if (Asking)
  1354.         return;
  1355.     SetLine(next_line(curwind->w_top, min(SIZE(curwind) - 1, arg_value() - 1)));
  1356. }
  1357.  
  1358. static int    LineNo,
  1359.         last_col,
  1360.         DoAutoNL;
  1361. static Window    *old_wind;    /* save the window we were in BEFORE
  1362.                    before we were called, if UseBuffers
  1363.                    is nonzero */
  1364.  
  1365. int    UseBuffers = FALSE;
  1366. int    TOabort = 0;
  1367.  
  1368. /* This initializes the typeout.  If send-typeout-to-buffers is set
  1369.    the buffer NAME is created (emptied if it already exists) and output
  1370.    goes to the buffer.  Otherwise output is drawn on the screen and
  1371.    erased by TOstop() */
  1372.  
  1373. /******************************************************/
  1374. void _fastcall TOstart (char *name, int auto_newline)
  1375. /******************************************************/
  1376. {
  1377.     if (UseBuffers) {
  1378.         old_wind = curwind;
  1379.         pop_wind(name, YES, B_SCRATCH);
  1380.     } else
  1381.         DisabledRedisplay = YES;
  1382.     TOabort = LineNo = last_col = 0;
  1383.     DoAutoNL = auto_newline;
  1384. }
  1385.  
  1386. #ifdef    STDARGS
  1387.     void
  1388. Typeout(char *fmt, ...)
  1389. #else
  1390.     /*VARARGS1*/ void
  1391. Typeout(fmt, va_alist)
  1392.     char    *fmt;
  1393.     va_dcl
  1394. #endif
  1395. {
  1396.     void _fastcall screen_buffer_flush (void);
  1397.     int _fastcall jgetchar(void);
  1398.     if (TOabort)
  1399.         return;
  1400.  
  1401.     if (!UseBuffers && (LineNo == ILI - 1)) {
  1402.         register  int    c;
  1403.  
  1404.         LineNo = 0;
  1405.         last_col = 0;
  1406.         f_mess("--more--");
  1407.         if ((c = jgetchar()) != ' ') {
  1408.             TOabort = YES;
  1409.             if (c != AbortChar && c != RUBOUT)
  1410.                 Ungetc(c);
  1411.             f_mess(NullStr);
  1412.             return;
  1413.         }
  1414.         f_mess(NullStr);
  1415.     }
  1416.  
  1417.     if (fmt) {
  1418.         char    string[132];
  1419.         va_list    ap;
  1420.  
  1421.         va_init(ap, fmt);
  1422.         format(string, sizeof string, fmt, ap);
  1423.         va_end(ap);
  1424.         if (UseBuffers)
  1425.             ins_str(string, NO);
  1426.         else {
  1427.             i_set(LineNo, last_col);
  1428.             (void) swrite(string, NO, YES);
  1429.             last_col = i_col;
  1430.         }
  1431.     }
  1432.     if (!UseBuffers) {
  1433.         PhysScreen[LineNo].s_id = -1;
  1434.         if (fmt == 0 || DoAutoNL == YES) {
  1435.             cl_eol();
  1436.             flusho();
  1437.             LineNo += 1;
  1438.             last_col = 0;
  1439.         }
  1440.     } else if (fmt == 0 || DoAutoNL != 0)
  1441.         ins_str("\n", NO);
  1442. }
  1443.  
  1444. /******************/
  1445. void TOstop (void)
  1446. /******************/
  1447. {
  1448.     void _fastcall screen_buffer_flush (void);
  1449.     int _fastcall jgetchar(void);
  1450.  
  1451.     int    c;
  1452.  
  1453.     if (UseBuffers) {
  1454.         ToFirst();
  1455.         SetWind(old_wind);
  1456.     } else {
  1457.         if (TOabort) {
  1458.             DisabledRedisplay = NO;
  1459.             return;
  1460.         }
  1461.         if (last_col != 0)
  1462.             Typeout((char *) 0);
  1463.         Typeout("----------");
  1464.         cl_eol();
  1465.         flusho();
  1466.         screen_buffer_flush (); /* ? */
  1467.         c = jgetchar();
  1468.         if (c != ' ')
  1469.             Ungetc(c);
  1470.         DisabledRedisplay = NO;
  1471.     }
  1472. }
  1473.