home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 8 / FreshFishVol8-CD1.bin / gnu / src / baseline / jove-4.14.6.lha / jove-4.14.6 / disp.c < prev    next >
C/C++ Source or Header  |  1992-01-10  |  30KB  |  1,497 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. #ifdef    IPROCS
  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. #ifdef MSDOS
  30. #define SIGHUP 99
  31. #endif
  32.  
  33. #include <signal.h>
  34.  
  35. private void
  36. #ifdef    ID_CHAR
  37.     DeTab proto((int, char *, char *, size_t, int)),
  38.     DelChar proto((int, int, int)),
  39.     InsChar proto((int, int, int, char *)),
  40. #endif
  41.     DoIDline proto((int)),
  42.     do_cl_eol proto((int)),
  43.     ModeLine proto((Window *)),
  44.     GotoDot proto((void)),
  45.     UpdLine proto((int)),
  46.     UpdWindow proto((Window *, int));
  47.  
  48. #ifdef    MSDOS
  49. extern void    dobell proto((int x));
  50. #else
  51. private void    dobell proto((int x));
  52. #endif
  53.  
  54. #ifdef    ID_CHAR
  55. private bool
  56.     IDchar proto ((char *, int, int)),
  57.     OkayDelete proto ((int, int, int)),
  58.     OkayInsert proto ((int, int));
  59. private int
  60.     NumSimilar proto ((char *, char *, int)),
  61.     IDcomp proto ((char *, char *, int));
  62. #endif
  63. private int
  64.     AddLines proto((int, int)),
  65.     DelLines proto((int, int));
  66.  
  67.  
  68.  
  69. int    DisabledRedisplay = NO;
  70.  
  71. /* Kludge windows gets called by the routines that delete lines from the
  72.    buffer.  If the w->w_line or w->w_top are deleted and this procedure
  73.    is not called, the redisplay routine will barf. */
  74.  
  75. void
  76. ChkWindows(line1, line2)
  77. Line    *line1,
  78.     *line2;
  79. {
  80.     register Window    *w = fwind;
  81.     register Line    *lp,
  82.             *lend = line2->l_next;
  83.  
  84.     do {
  85.         if (w->w_bufp == curbuf) {
  86.             for (lp = line1->l_next; lp != lend; lp = lp->l_next) {
  87.                 if (lp == w->w_top)
  88.                     w->w_flags |= W_TOPGONE;
  89.                 if (lp == w->w_line)
  90.                     w->w_flags |= W_CURGONE;
  91.             }
  92.         }
  93.         w = w->w_next;
  94.     } while (w != fwind);
  95. }
  96.  
  97. /* Deleted and killed Lines are about to be recycled: check for dangling refs */
  98.  
  99. void
  100. ChkWinLines()
  101. {
  102.     register Window    *w = fwind;
  103.  
  104.     do {
  105.         if (w->w_top == NULL || w->w_top->l_dline == NULL_DADDR)
  106.             w->w_flags |= W_TOPGONE;
  107.         if (w->w_line == NULL || w->w_line->l_dline == NULL_DADDR)
  108.             w->w_flags |= W_CURGONE;
  109.         w = w->w_next;
  110.     } while (w != fwind);
  111. }
  112.  
  113. private bool    RingBell;    /* So if we have a lot of errors ...
  114.                   ring the bell only ONCE */
  115.  
  116. void
  117. redisplay()
  118. {
  119.     register Window    *w = fwind;
  120.     int    lineno,
  121.         done_ID = NO,
  122.         i;
  123.     register struct scrimage    *des_p,
  124.                     *phys_p;
  125.  
  126.     if (DisabledRedisplay == YES)
  127.         return;
  128.     curwind->w_line = curwind->w_bufp->b_dot;
  129.     curwind->w_char = curwind->w_bufp->b_char;
  130. #ifdef    MAC
  131.     InputPending = NO;
  132. #else
  133.     if ((InputPending = charp()) != NO)    /* calls CheckEvent, which could */
  134.         return;    /* result in a call to rediplay(). We don't want that. */
  135. #endif
  136. #ifdef    BSD_SIGS
  137.     if (UpdFreq)
  138.         SigHold(SIGALRM);
  139. #endif
  140.     if (RingBell) {
  141.         dobell(1);
  142.         RingBell = NO;
  143.     }
  144.     AbortCnt = BufSize;        /* initialize this now */
  145.     if (UpdMesg)
  146.         DrawMesg(YES);
  147.  
  148.     for (lineno = 0, w = fwind; lineno < ILI; w = w->w_next) {
  149.         UpdWindow(w, lineno);
  150.         lineno += w->w_height;
  151.     }
  152.  
  153.     UpdModLine = NO;/* Now that we've called update window, we can
  154.                assume that the modeline will be updated.  But
  155.                if while redrawing the modeline the user types
  156.                a character, ModeLine() is free to set this on
  157.                again so that the modeline will be fully drawn
  158.                at the next redisplay. */
  159.  
  160.     des_p = DesiredScreen;
  161.     phys_p = PhysScreen;
  162.     for (i = 0; i < ILI; i++, des_p++, phys_p++) {
  163.         if (!done_ID && (des_p->s_id != phys_p->s_id)) {
  164.             DoIDline(i);
  165.             done_ID = YES;
  166.         }
  167.         if ((des_p->s_flags & (DIRTY | L_MOD)) ||
  168.             (des_p->s_id != phys_p->s_id) ||
  169.             (des_p->s_vln != phys_p->s_vln) ||
  170.             (des_p->s_offset != phys_p->s_offset))
  171.             UpdLine(i);
  172.         if (InputPending)
  173.             goto ret;
  174.     }
  175.  
  176.     if (Asking) {
  177.         Placur(LI - 1, min(CO - 2, calc_pos(mesgbuf, AskingWidth)));
  178.             /* Nice kludge */
  179.         flushscreen();
  180.     } else {
  181.         GotoDot();
  182.     }
  183. ret:
  184.     ;    /* yuck */
  185.  
  186. #ifdef    BSD_SIGS
  187.     if (UpdFreq)
  188.         SigRelse(SIGALRM);
  189. #endif
  190. #ifdef    MAC
  191.     if (Windchange)
  192.         docontrols();
  193. #endif    /* MAC */
  194. }
  195.  
  196. #ifndef    IBMPC
  197. private void
  198. dobell(n)
  199. int    n;
  200. {
  201.     while (--n >= 0) {
  202. #ifndef    MAC
  203.         if (VisBell && VB)
  204.             putstr(VB);
  205.         else
  206.             putpad(BL, 1);
  207. #else
  208.         SysBeep(5);
  209. #endif
  210.     }
  211.     flushscreen();
  212. }
  213. #endif    /* IBMPC */
  214.  
  215. /* find_pos() returns the position on the line, that C_CHAR represents
  216.    in LINE */
  217.  
  218. private int
  219. find_pos(line, c_char)
  220. Line    *line;
  221. int    c_char;
  222. {
  223.     return calc_pos(lcontents(line), c_char);
  224. }
  225.  
  226. int
  227. calc_pos(lp, c_char)
  228. register char    *lp;
  229. register int    c_char;
  230. {
  231.     register int    pos = 0;
  232.     register int    c;
  233.  
  234.  
  235.     while ((--c_char >= 0) && ((c = *lp++) & CHARMASK) != 0) {
  236.         if (c == '\t')
  237.             pos += (tabstop - (pos % tabstop));
  238.         else if (jiscntrl(c))
  239.             pos += 2;
  240.         else
  241.             pos += 1;
  242.     }
  243.     return pos;
  244. }
  245.  
  246. bool    UpdModLine = NO,
  247.     UpdMesg = NO;
  248.  
  249. private void
  250. DoIDline(start)
  251. int    start;
  252. {
  253.     register struct scrimage    *des_p = &DesiredScreen[start];
  254.     struct scrimage    *phys_p = &PhysScreen[start];
  255.     register int    i,
  256.             j;
  257.  
  258.     /* Some changes have been made.  Try for insert or delete lines.
  259.        If either case has happened, Addlines and/or DelLines will do
  260.        necessary scrolling, also CONVERTING PhysScreen to account for the
  261.        physical changes.  The comparison continues from where the
  262.        insertion/deletion takes place; this doesn't happen very often,
  263.        usually it happens with more than one window with the same
  264.        buffer. */
  265.  
  266.     if (!CanScroll)
  267.         return;        /* We should never have been called! */
  268.  
  269.     for (i = start; i < ILI; i++, des_p++, phys_p++)
  270.         if (des_p->s_id != phys_p->s_id)
  271.             break;
  272.  
  273.     for (; i < ILI; i++) {
  274.         for (j = i + 1; j < ILI; j++) {
  275.             des_p = &DesiredScreen[j];
  276.             phys_p = &PhysScreen[j];
  277.             if (des_p->s_id != 0 && des_p->s_id == phys_p->s_id)
  278.                 break;
  279.             if (des_p->s_id == PhysScreen[i].s_id) {
  280.                 if (des_p->s_id == 0)
  281.                     continue;
  282.                 if (AddLines(i, j - i)) {
  283.                     DoIDline(j);
  284.                     return;
  285.                 }
  286.                 break;
  287.             }
  288.             if ((des_p = &DesiredScreen[i])->s_id == phys_p->s_id) {
  289.                 if (des_p->s_id == 0)
  290.                     continue;
  291.                 if (DelLines(i, j - i)) {
  292.                     DoIDline(i);
  293.                     return;
  294.                 }
  295.                 break;
  296.             }
  297.         }
  298.     }
  299. }
  300.  
  301. /* Make DesiredScreen reflect what the screen should look like when we are done
  302.    with the redisplay.  This deals with horizontal scrolling.  Also makes
  303.    sure the current line of the Window is in the window. */
  304.  
  305. bool    ScrollAll = NO;
  306.  
  307. private void
  308. UpdWindow(w, start)
  309. register Window    *w;
  310. int    start;
  311. {
  312.     Line    *lp;
  313.     int    i,
  314.         upper,        /* top of window */
  315.         lower,        /* bottom of window */
  316.         strt_col,    /* starting print column of current line */
  317.         ntries = 0;    /* # of tries at updating window */
  318.     register struct scrimage    *des_p,
  319.                     *phys_p;
  320.     Buffer    *bp = w->w_bufp;
  321.  
  322. retry:
  323.     if (w->w_flags & W_CURGONE) {
  324.         w->w_line = bp->b_dot;
  325.         w->w_char = bp->b_char;
  326.     }
  327.     if (w->w_flags & W_TOPGONE)
  328.         CentWind(w);    /* reset topline of screen */
  329.     w->w_flags &= ~(W_CURGONE | W_TOPGONE);
  330.  
  331.     /* make sure that the current line is in the window */
  332.     upper = start;
  333.     lower = upper + w->w_height - 1;    /* don't include modeline */
  334.     for (i = upper, lp = w->w_top; i < lower && lp != NULL; lp = lp->l_next, i++)
  335.         if (lp == w->w_line)
  336.             break;
  337.     if (i == lower || lp == NULL) {
  338.         ntries += 1;
  339.         if (ntries == 1) {
  340.             CalcWind(w);
  341.             goto retry;
  342.         } else if (ntries == 2) {
  343.             w->w_top = w->w_line = w->w_bufp->b_first;
  344.             writef("\rERROR in redisplay: I got hopelessly lost!");
  345.             dobell(2);
  346.             goto retry;
  347.         } else if (ntries == 3) {
  348.             writef("\n\rOops, still lost, quitting ...\r\n");
  349.             finish(SIGHUP);
  350.         }
  351.     }
  352.  
  353.     /* first do some calculations for the current line */
  354.     {
  355.         int    diff = (w->w_flags & W_NUMLINES) ? 8 : 0,
  356.             end_col;
  357.  
  358.         strt_col = ScrollAll? w->w_LRscroll : PhysScreen[i].s_offset;
  359.         end_col = strt_col + (CO - 2) - diff;
  360.         /* Right now we are displaying from strt_col to
  361.            end_col of the buffer line.  These are PRINT
  362.            columns, not actual characters. */
  363.         w->w_dotcol = find_pos(w->w_line, w->w_char);
  364.         /*