home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume1 / 8711 / microemacs-3.9 / 3 < prev    next >
Text File  |  1987-11-17  |  26KB  |  1,170 lines

  1. Article 79 of comp.sources.misc:
  2. Path: tut!osu-cis!cbosgd!mandrill!hal!ncoast!allbery
  3. From: nwd@j.cc.purdue.edu (Daniel Lawrence)
  4. Newsgroups: comp.sources.misc
  5. Subject: MicroEmacs 3.9 (Part 3 of 16)
  6. Message-ID: <5650@ncoast.UUCP>
  7. Date: 14 Nov 87 21:07:14 GMT
  8. Sender: allbery@ncoast.UUCP
  9. Lines: 1155
  10. Approved: allbery@ncoast.UUCP
  11. X-Archive: comp.sources.misc/microemacs-3.9/2
  12.  
  13. # This is a shar archive.
  14. # Remove everything above this line.
  15. # Run the file through sh, not csh.
  16. # (type `sh mes.3')
  17. # If you do not see the message
  18. #    `mes.3 completed!'
  19. # then the file was incomplete.
  20. echo extracting - display.c
  21. sed 's/^X//' > display.c << 'FRIDAY_NIGHT'
  22. X/*
  23. X * The functions in this file handle redisplay. There are two halves, the
  24. X * ones that update the virtual display screen, and the ones that make the
  25. X * physical display screen the same as the virtual display screen. These
  26. X * functions use hints that are left in the windows by the commands.
  27. X *
  28. X */
  29. X
  30. X#include        <stdio.h>
  31. X#include    "estruct.h"
  32. X#include        "edef.h"
  33. X
  34. Xtypedef struct  VIDEO {
  35. X        int    v_flag;                 /* Flags */
  36. X#if    COLOR
  37. X    int    v_fcolor;        /* current forground color */
  38. X    int    v_bcolor;        /* current background color */
  39. X    int    v_rfcolor;        /* requested forground color */
  40. X    int    v_rbcolor;        /* requested background color */
  41. X#endif
  42. X        char    v_text[1];              /* Screen data. */
  43. X}       VIDEO;
  44. X
  45. X#define VFCHG   0x0001                  /* Changed flag            */
  46. X#define    VFEXT    0x0002            /* extended (beyond column 80)    */
  47. X#define    VFREV    0x0004            /* reverse video status        */
  48. X#define    VFREQ    0x0008            /* reverse video request    */
  49. X#define    VFCOL    0x0010            /* color change requested    */
  50. X
  51. XVIDEO   **vscreen;                      /* Virtual screen. */
  52. X#if    MEMMAP == 0
  53. XVIDEO   **pscreen;                      /* Physical screen. */
  54. X#endif
  55. X
  56. X/*
  57. X * Initialize the data structures used by the display code. The edge vectors
  58. X * used to access the screens are set up. The operating system's terminal I/O
  59. X * channel is set up. All the other things get initialized at compile time.
  60. X * The original window has "WFCHG" set, so that it will get completely
  61. X * redrawn on the first call to "update".
  62. X */
  63. Xvtinit()
  64. X{
  65. X    register int i;
  66. X    register VIDEO *vp;
  67. X    char *malloc();
  68. X
  69. X    TTopen();        /* open the screen */
  70. X    TTkopen();        /* open the keyboard */
  71. X    TTrev(FALSE);
  72. X    vscreen = (VIDEO **) malloc(term.t_mrow*sizeof(VIDEO *));
  73. X
  74. X    if (vscreen == NULL)
  75. X        exit(1);
  76. X
  77. X#if    MEMMAP == 0
  78. X    pscreen = (VIDEO **) malloc(term.t_mrow*sizeof(VIDEO *));
  79. X
  80. X    if (pscreen == NULL)
  81. X        exit(1);
  82. X#endif
  83. X
  84. X    for (i = 0; i < term.t_mrow; ++i)
  85. X        {
  86. X        vp = (VIDEO *) malloc(sizeof(VIDEO)+term.t_mcol);
  87. X
  88. X        if (vp == NULL)
  89. X            exit(1);
  90. X
  91. X    vp->v_flag = 0;
  92. X#if    COLOR
  93. X    vp->v_rfcolor = 7;
  94. X    vp->v_rbcolor = 0;
  95. X#endif
  96. X        vscreen[i] = vp;
  97. X#if    MEMMAP == 0
  98. X        vp = (VIDEO *) malloc(sizeof(VIDEO)+term.t_mcol);
  99. X
  100. X        if (vp == NULL)
  101. X            exit(1);
  102. X
  103. X    vp->v_flag = 0;
  104. X        pscreen[i] = vp;
  105. X#endif
  106. X        }
  107. X}
  108. X
  109. X#if    CLEAN
  110. X/* free up all the dynamically allocated video structures */
  111. X
  112. Xvtfree()
  113. X{
  114. X    int i;
  115. X    for (i = 0; i < term.t_mrow; ++i) {
  116. X        free(vscreen[i]);
  117. X#if    MEMMAP == 0
  118. X        free(pscreen[i]);
  119. X#endif
  120. X    }
  121. X    free(vscreen);
  122. X#if    MEMMAP == 0
  123. X    free(pscreen);
  124. X#endif
  125. X}
  126. X#endif
  127. X
  128. X/*
  129. X * Clean up the virtual terminal system, in anticipation for a return to the
  130. X * operating system. Move down to the last line and clear it out (the next
  131. X * system prompt will be written in the line). Shut down the channel to the
  132. X * terminal.
  133. X */
  134. Xvttidy()
  135. X{
  136. X    mlerase();
  137. X    movecursor(term.t_nrow, 0);
  138. X    TTflush();
  139. X    TTclose();
  140. X    TTkclose();
  141. X}
  142. X
  143. X/*
  144. X * Set the virtual cursor to the specified row and column on the virtual
  145. X * screen. There is no checking for nonsense values; this might be a good
  146. X * idea during the early stages.
  147. X */
  148. Xvtmove(row, col)
  149. X{
  150. X    vtrow = row;
  151. X    vtcol = col;
  152. X}
  153. X
  154. X/* Write a character to the virtual screen. The virtual row and
  155. X   column are updated. If we are not yet on left edge, don't print
  156. X   it yet. If the line is too long put a "$" in the last column.
  157. X   This routine only puts printing characters into the virtual
  158. X   terminal buffers. Only column overflow is checked.
  159. X*/
  160. X
  161. Xvtputc(c)
  162. X
  163. Xint c;
  164. X
  165. X{
  166. X    register VIDEO *vp;    /* ptr to line being updated */
  167. X
  168. X    vp = vscreen[vtrow];
  169. X
  170. X    if (c == '\t') {
  171. X        do {
  172. X            vtputc(' ');
  173. X        } while (((vtcol + taboff)&0x07) != 0);
  174. X    } else if (vtcol >= term.t_ncol) {
  175. X        ++vtcol;
  176. X        vp->v_text[term.t_ncol - 1] = '$';
  177. X    } else if (c < 0x20 || c == 0x7F) {
  178. X        vtputc('^');
  179. X        vtputc(c ^ 0x40);
  180. X    } else {
  181. X        if (vtcol >= 0)
  182. X            vp->v_text[vtcol] = c;
  183. X        ++vtcol;
  184. X    }
  185. X}
  186. X
  187. X/*
  188. X * Erase from the end of the software cursor to the end of the line on which
  189. X * the software cursor is located.
  190. X */
  191. Xvteeol()
  192. X{
  193. X    register VIDEO      *vp;
  194. X
  195. X    vp = vscreen[vtrow];
  196. X    while (vtcol < term.t_ncol)
  197. X        vp->v_text[vtcol++] = ' ';
  198. X}
  199. X
  200. X/* upscreen:    user routine to force a screen update
  201. X        always finishes complete update        */
  202. X
  203. Xupscreen(f, n)
  204. X
  205. X{
  206. X    update(TRUE);
  207. X    return(TRUE);
  208. X}
  209. X
  210. X/*
  211. X * Make sure that the display is right. This is a three part process. First,
  212. X * scan through all of the windows looking for dirty ones. Check the framing,
  213. X * and refresh the screen. Second, make sure that "currow" and "curcol" are
  214. X * correct for the current window. Third, make the virtual and physical
  215. X * screens the same.
  216. X */
  217. Xupdate(force)
  218. X
  219. Xint force;    /* force update past type ahead? */
  220. X
  221. X{
  222. X    register WINDOW *wp;
  223. X
  224. X#if    TYPEAH
  225. X    if (force == FALSE && typahead())
  226. X        return(TRUE);
  227. X#endif
  228. X#if    VISMAC == 0
  229. X    if (force == FALSE && kbdmode == PLAY)
  230. X        return(TRUE);
  231. X#endif
  232. X
  233. X    /* update any windows that need refreshing */
  234. X    wp = wheadp;
  235. X    while (wp != NULL) {
  236. X        if (wp->w_flag) {
  237. X            /* if the window has changed, service it */
  238. X            reframe(wp);    /* check the framing */
  239. X            if ((wp->w_flag & ~WFMODE) == WFEDIT)
  240. X                updone(wp);    /* update EDITed line */
  241. X            else if (wp->w_flag & ~WFMOVE)
  242. X                updall(wp);    /* update all lines */
  243. X            if (wp->w_flag & WFMODE)
  244. X                modeline(wp);    /* update modeline */
  245. X            wp->w_flag = 0;
  246. X            wp->w_force = 0;
  247. X        }
  248. X        /* on to the next window */
  249. X        wp = wp->w_wndp;
  250. X    }
  251. X
  252. X    /* recalc the current hardware cursor location */
  253. X    updpos();
  254. X
  255. X#if    MEMMAP
  256. X    /* update the cursor and flush the buffers */
  257. X    movecursor(currow, curcol - lbound);
  258. X#endif
  259. X
  260. X    /* check for lines to de-extend */
  261. X    upddex();
  262. X
  263. X    /* if screen is garbage, re-plot it */
  264. X    if (sgarbf != FALSE)
  265. X        updgar();
  266. X
  267. X    /* update the virtual screen to the physical screen */
  268. X    updupd(force);
  269. X
  270. X    /* update the cursor and flush the buffers */
  271. X    movecursor(currow, curcol - lbound);
  272. X    TTflush();
  273. X    return(TRUE);
  274. X}
  275. X
  276. X/*    reframe:    check to see if the cursor is on in the window
  277. X            and re-frame it if needed or wanted        */
  278. X
  279. Xreframe(wp)
  280. X
  281. XWINDOW *wp;
  282. X
  283. X{
  284. X    register LINE *lp;
  285. X    register int i;
  286. X
  287. X    /* if not a requested reframe, check for a needed one */
  288. X    if ((wp->w_flag & WFFORCE) == 0) {
  289. X        lp = wp->w_linep;
  290. X        for (i = 0; i < wp->w_ntrows; i++) {
  291. X
  292. X            /* if the line is in the window, no reframe */
  293. X            if (lp == wp->w_dotp)
  294. X                return(TRUE);
  295. X
  296. X            /* if we are at the end of the file, reframe */
  297. X            if (lp == wp->w_bufp->b_linep)
  298. X                break;
  299. X
  300. X            /* on to the next line */
  301. X            lp = lforw(lp);
  302. X        }
  303. X    }
  304. X
  305. X    /* reaching here, we need a window refresh */
  306. X    i = wp->w_force;
  307. X
  308. X    /* how far back to reframe? */
  309. X    if (i > 0) {        /* only one screen worth of lines max */
  310. X        if (--i >= wp->w_ntrows)
  311. X            i = wp->w_ntrows - 1;
  312. X    } else if (i < 0) {    /* negative update???? */
  313. X        i += wp->w_ntrows;
  314. X        if (i < 0)
  315. X            i = 0;
  316. X    } else
  317. X        i = wp->w_ntrows / 2;
  318. X
  319. X    /* backup to new line at top of window */
  320. X    lp = wp->w_dotp;
  321. X    while (i != 0 && lback(lp) != wp->w_bufp->b_linep) {
  322. X        --i;
  323. X        lp = lback(lp);
  324. X    }
  325. X
  326. X    /* and reset the current line at top of window */
  327. X    wp->w_linep = lp;
  328. X    wp->w_flag |= WFHARD;
  329. X    wp->w_flag &= ~WFFORCE;
  330. X    return(TRUE);
  331. X}
  332. X
  333. X/*    updone:    update the current line    to the virtual screen        */
  334. X
  335. Xupdone(wp)
  336. X
  337. XWINDOW *wp;    /* window to update current line in */
  338. X
  339. X{
  340. X    register LINE *lp;    /* line to update */
  341. X    register int sline;    /* physical screen line to update */
  342. X    register int i;
  343. X
  344. X    /* search down the line we want */
  345. X    lp = wp->w_linep;
  346. X    sline = wp->w_toprow;
  347. X    while (lp != wp->w_dotp) {
  348. X        ++sline;
  349. X        lp = lforw(lp);
  350. X    }
  351. X
  352. X    /* and update the virtual line */
  353. X    vscreen[sline]->v_flag |= VFCHG;
  354. X    vscreen[sline]->v_flag &= ~VFREQ;
  355. X    vtmove(sline, 0);
  356. X    for (i=0; i < llength(lp); ++i)
  357. X        vtputc(lgetc(lp, i));
  358. X#if    COLOR
  359. X    vscreen[sline]->v_rfcolor = wp->w_fcolor;
  360. X    vscreen[sline]->v_rbcolor = wp->w_bcolor;
  361. X#endif
  362. X    vteeol();
  363. X}
  364. X
  365. X/*    updall:    update all the lines in a window on the virtual screen */
  366. X
  367. Xupdall(wp)
  368. X
  369. XWINDOW *wp;    /* window to update lines in */
  370. X
  371. X{
  372. X    register LINE *lp;    /* line to update */
  373. X    register int sline;    /* physical screen line to update */
  374. X    register int i;
  375. X
  376. X    /* search down the lines, updating them */
  377. X    lp = wp->w_linep;
  378. X    sline = wp->w_toprow;
  379. X    while (sline < wp->w_toprow + wp->w_ntrows) {
  380. X
  381. X        /* and update the virtual line */
  382. X        vscreen[sline]->v_flag |= VFCHG;
  383. X        vscreen[sline]->v_flag &= ~VFREQ;
  384. X        vtmove(sline, 0);
  385. X        if (lp != wp->w_bufp->b_linep) {
  386. X            /* if we are not at the end */
  387. X            for (i=0; i < llength(lp); ++i)
  388. X                vtputc(lgetc(lp, i));
  389. X            lp = lforw(lp);
  390. X        }
  391. X
  392. X        /* on to the next one */
  393. X#if    COLOR
  394. X        vscreen[sline]->v_rfcolor = wp->w_fcolor;
  395. X        vscreen[sline]->v_rbcolor = wp->w_bcolor;
  396. X#endif
  397. X        vteeol();
  398. X        ++sline;
  399. X    }
  400. X
  401. X}
  402. X
  403. X/*    updpos:    update the position of the hardware cursor and handle extended
  404. X        lines. This is the only update for simple moves.    */
  405. X
  406. Xupdpos()
  407. X
  408. X{
  409. X    register LINE *lp;
  410. X    register int c;
  411. X    register int i;
  412. X
  413. X    /* find the current row */
  414. X    lp = curwp->w_linep;
  415. X    currow = curwp->w_toprow;
  416. X    while (lp != curwp->w_dotp) {
  417. X        ++currow;
  418. X        lp = lforw(lp);
  419. X    }
  420. X
  421. X    /* find the current column */
  422. X    curcol = 0;
  423. X    i = 0;
  424. X    while (i < curwp->w_doto) {
  425. X        c = lgetc(lp, i++);
  426. X        if (c == '\t')
  427. X            curcol |= 0x07;
  428. X        else
  429. X            if (c < 0x20 || c == 0x7f)
  430. X                ++curcol;
  431. X
  432. X        ++curcol;
  433. X    }
  434. X
  435. X    /* if extended, flag so and update the virtual line image */
  436. X    if (curcol >=  term.t_ncol - 1) {
  437. X        vscreen[currow]->v_flag |= (VFEXT | VFCHG);
  438. X        updext();
  439. X    } else
  440. X        lbound = 0;
  441. X}
  442. X
  443. X/*    upddex:    de-extend any line that derserves it        */
  444. X
  445. Xupddex()
  446. X
  447. X{
  448. X    register WINDOW *wp;
  449. X    register LINE *lp;
  450. X    register int i,j;
  451. X
  452. X    wp = wheadp;
  453. X
  454. X    while (wp != NULL) {
  455. X        lp = wp->w_linep;
  456. X        i = wp->w_toprow;
  457. X
  458. X        while (i < wp->w_toprow + wp->w_ntrows) {
  459. X            if (vscreen[i]->v_flag & VFEXT) {
  460. X                if ((wp != curwp) || (lp != wp->w_dotp) ||
  461. X                   (curcol < term.t_ncol - 1)) {
  462. X                    vtmove(i, 0);
  463. X                    for (j = 0; j < llength(lp); ++j)
  464. X                        vtputc(lgetc(lp, j));
  465. X                    vteeol();
  466. X
  467. X                    /* this line no longer is extended */
  468. X                    vscreen[i]->v_flag &= ~VFEXT;
  469. X                    vscreen[i]->v_flag |= VFCHG;
  470. X                }
  471. X            }
  472. X            lp = lforw(lp);
  473. X            ++i;
  474. X        }
  475. X        /* and onward to the next window */
  476. X        wp = wp->w_wndp;
  477. X    }
  478. X}
  479. X
  480. X/*    updgar:    if the screen is garbage, clear the physical screen and
  481. X        the virtual screen and force a full update        */
  482. X
  483. Xupdgar()
  484. X
  485. X{
  486. X    register char *txt;
  487. X    register int i,j;
  488. X
  489. X    for (i = 0; i < term.t_nrow; ++i) {
  490. X        vscreen[i]->v_flag |= VFCHG;
  491. X#if    REVSTA
  492. X        vscreen[i]->v_flag &= ~VFREV;
  493. X#endif
  494. X#if    COLOR
  495. X        vscreen[i]->v_fcolor = gfcolor;
  496. X        vscreen[i]->v_bcolor = gbcolor;
  497. X#endif
  498. X#if    MEMMAP == 0
  499. X        txt = pscreen[i]->v_text;
  500. X        for (j = 0; j < term.t_ncol; ++j)
  501. X            txt[j] = ' ';
  502. X#endif
  503. X    }
  504. X
  505. X    movecursor(0, 0);         /* Erase the screen. */
  506. X    (*term.t_eeop)();
  507. X    sgarbf = FALSE;             /* Erase-page clears */
  508. X    mpresf = FALSE;             /* the message area. */
  509. X#if    COLOR
  510. X    mlerase();            /* needs to be cleared if colored */
  511. X#endif
  512. X}
  513. X
  514. X/*    updupd:    update the physical screen from the virtual screen    */
  515. X
  516. Xupdupd(force)
  517. X
  518. Xint force;    /* forced update flag */
  519. X
  520. X{
  521. X    register VIDEO *vp1;
  522. X    register int i;
  523. X
  524. X    for (i = 0; i < term.t_nrow; ++i) {
  525. X        vp1 = vscreen[i];
  526. X
  527. X        /* for each line that needs to be updated*/
  528. X        if ((vp1->v_flag & VFCHG) != 0) {
  529. X#if    TYPEAH
  530. X            if (force == FALSE && typahead())
  531. X                return(TRUE);
  532. X#endif
  533. X#if    MEMMAP
  534. X            updateline(i, vp1);
  535. X#else
  536. X            updateline(i, vp1, pscreen[i]);
  537. X#endif
  538. X        }
  539. X    }
  540. X    return(TRUE);
  541. X}
  542. X
  543. X/*    updext: update the extended line which the cursor is currently
  544. X        on at a column greater than the terminal width. The line
  545. X        will be scrolled right or left to let the user see where
  546. X        the cursor is
  547. X                                */
  548. X
  549. Xupdext()
  550. X
  551. X{
  552. X    register int rcursor;    /* real cursor location */
  553. X    register LINE *lp;    /* pointer to current line */
  554. X    register int j;        /* index into line */
  555. X
  556. X    /* calculate what column the real cursor will end up in */
  557. X    rcursor = ((curcol - term.t_ncol) % term.t_scrsiz) + term.t_margin;
  558. X    taboff = lbound = curcol - rcursor + 1;
  559. X
  560. X    /* scan through the line outputing characters to the virtual screen */
  561. X    /* once we reach the left edge                    */
  562. X    vtmove(currow, -lbound);    /* start scanning offscreen */
  563. X    lp = curwp->w_dotp;        /* line to output */
  564. X    for (j=0; j<llength(lp); ++j)    /* until the end-of-line */
  565. X        vtputc(lgetc(lp, j));
  566. X
  567. X    /* truncate the virtual line, restore tab offset */
  568. X    vteeol();
  569. X    taboff = 0;
  570. X
  571. X    /* and put a '$' in column 1 */
  572. X    vscreen[currow]->v_text[0] = '$';
  573. X}
  574. X
  575. X/*
  576. X * Update a single line. This does not know how to use insert or delete
  577. X * character sequences; we are using VT52 functionality. Update the physical
  578. X * row and column variables. It does try an exploit erase to end of line. The
  579. X * RAINBOW version of this routine uses fast video.
  580. X */
  581. X#if    MEMMAP
  582. X/*    UPDATELINE specific code for the IBM-PC and other compatables */
  583. X
  584. Xupdateline(row, vp1)
  585. X
  586. Xint row;        /* row of screen to update */
  587. Xstruct VIDEO *vp1;    /* virtual screen image */
  588. X
  589. X{
  590. X#if    COLOR
  591. X    scwrite(row, vp1->v_text, vp1->v_rfcolor, vp1->v_rbcolor);
  592. X    vp1->v_fcolor = vp1->v_rfcolor;
  593. X    vp1->v_bcolor = vp1->v_rbcolor;
  594. X#else
  595. X    if (vp1->v_flag & VFREQ)
  596. X        scwrite(row, vp1->v_text, 0, 7);
  597. X    else
  598. X        scwrite(row, vp1->v_text, 7, 0);
  599. X#endif
  600. X    vp1->v_flag &= ~(VFCHG | VFCOL);    /* flag this line as changed */
  601. X
  602. X}
  603. X
  604. X#else
  605. X
  606. Xupdateline(row, vp1, vp2)
  607. X
  608. Xint row;        /* row of screen to update */
  609. Xstruct VIDEO *vp1;    /* virtual screen image */
  610. Xstruct VIDEO *vp2;    /* physical screen image */
  611. X
  612. X{
  613. X#if RAINBOW
  614. X/*    UPDATELINE specific code for the DEC rainbow 100 micro    */
  615. X
  616. X    register char *cp1;
  617. X    register char *cp2;
  618. X    register int nch;
  619. X
  620. X    /* since we don't know how to make the rainbow do this, turn it off */
  621. X    flags &= (~VFREV & ~VFREQ);
  622. X
  623. X    cp1 = &vp1->v_text[0];                    /* Use fast video. */
  624. X    cp2 = &vp2->v_text[0];
  625. X    putline(row+1, 1, cp1);
  626. X    nch = term.t_ncol;
  627. X
  628. X    do
  629. X        {
  630. X        *cp2 = *cp1;
  631. X        ++cp2;
  632. X        ++cp1;
  633. X        }
  634. X    while (--nch);
  635. X    *flags &= ~VFCHG;
  636. X#else
  637. X/*    UPDATELINE code for all other versions        */
  638. X
  639. X    register char *cp1;
  640. X    register char *cp2;
  641. X    register char *cp3;
  642. X    register char *cp4;
  643. X    register char *cp5;
  644. X    register int nbflag;    /* non-blanks to the right flag? */
  645. X    int rev;        /* reverse video flag */
  646. X    int req;        /* reverse video request flag */
  647. X
  648. X
  649. X    /* set up pointers to virtual and physical lines */
  650. X    cp1 = &vp1->v_text[0];
  651. X    cp2 = &vp2->v_text[0];
  652. X
  653. X#if    COLOR
  654. X    TTforg(vp1->v_rfcolor);
  655. X    TTbacg(vp1->v_rbcolor);
  656. X#endif
  657. X
  658. X#if    REVSTA | COLOR
  659. X    /* if we need to change the reverse video status of the
  660. X       current line, we need to re-write the entire line     */
  661. X    rev = (vp1->v_flag & VFREV) == VFREV;
  662. X    req = (vp1->v_flag & VFREQ) == VFREQ;
  663. X    if ((rev != req)
  664. X#if    COLOR
  665. X        || (vp1->v_fcolor != vp1->v_rfcolor) || (vp1->v_bcolor != vp1->v_rbcolor)
  666. X#endif
  667. X#if    HP150
  668. X    /* the HP150 has some reverse video problems */
  669. X        || req || rev
  670. X#endif
  671. X            ) {
  672. X        movecursor(row, 0);    /* Go to start of line. */
  673. X        /* set rev video if needed */
  674. X        if (rev != req)
  675. X            (*term.t_rev)(req);
  676. X
  677. X        /* scan through the line and dump it to the screen and
  678. X           the virtual screen array                */
  679. X        cp3 = &vp1->v_text[term.t_ncol];
  680. X        while (cp1 < cp3) {
  681. X            TTputc(*cp1);
  682. X            ++ttcol;
  683. X            *cp2++ = *cp1++;
  684. X        }
  685. X        /* turn rev video off */
  686. X        if (rev != req)
  687. X            (*term.t_rev)(FALSE);
  688. X
  689. X        /* update the needed flags */
  690. X        vp1->v_flag &= ~VFCHG;
  691. X        if (req)
  692. X            vp1->v_flag |= VFREV;
  693. X        else
  694. X            vp1->v_flag &= ~VFREV;
  695. X#if    COLOR
  696. X        vp1->v_fcolor = vp1->v_rfcolor;
  697. X        vp1->v_bcolor = vp1->v_rbcolor;
  698. X#endif
  699. X        return(TRUE);
  700. X    }
  701. X#endif
  702. X
  703. X    /* advance past any common chars at the left */
  704. X    while (cp1 != &vp1->v_text[term.t_ncol] && cp1[0] == cp2[0]) {
  705. X        ++cp1;
  706. X        ++cp2;
  707. X    }
  708. X
  709. X/* This can still happen, even though we only call this routine on changed
  710. X * lines. A hard update is always done when a line splits, a massive
  711. X * change is done, or a buffer is displayed twice. This optimizes out most
  712. X * of the excess updating. A lot of computes are used, but these tend to
  713. X * be hard operations that do a lot of update, so I don't really care.
  714. X */
  715. X    /* if both lines are the same, no update needs to be done */
  716. X    if (cp1 == &vp1->v_text[term.t_ncol]) {
  717. X         vp1->v_flag &= ~VFCHG;        /* flag this line is changed */
  718. X        return(TRUE);
  719. X    }
  720. X
  721. X    /* find out if there is a match on the right */
  722. X    nbflag = FALSE;
  723. X    cp3 = &vp1->v_text[term.t_ncol];
  724. X    cp4 = &vp2->v_text[term.t_ncol];
  725. X
  726. X    while (cp3[-1] == cp4[-1]) {
  727. X        --cp3;
  728. X        --cp4;
  729. X        if (cp3[0] != ' ')        /* Note if any nonblank */
  730. X            nbflag = TRUE;        /* in right match. */
  731. X    }
  732. X
  733. X    cp5 = cp3;
  734. X
  735. X    /* Erase to EOL ? */
  736. X    if (nbflag == FALSE && eolexist == TRUE && (req != TRUE)) {
  737. X        while (cp5!=cp1 && cp5[-1]==' ')
  738. X            --cp5;
  739. X
  740. X        if (cp3-cp5 <= 3)        /* Use only if erase is */
  741. X            cp5 = cp3;        /* fewer characters. */
  742. X    }
  743. X
  744. X    movecursor(row, cp1 - &vp1->v_text[0]);    /* Go to start of line. */
  745. X#if    REVSTA
  746. X    TTrev(rev);
  747. X#endif
  748. X
  749. X    while (cp1 != cp5) {        /* Ordinary. */
  750. X        TTputc(*cp1);
  751. X        ++ttcol;
  752. X        *cp2++ = *cp1++;
  753. X    }
  754. X
  755. X    if (cp5 != cp3) {        /* Erase. */
  756. X        TTeeol();
  757. X        while (cp1 != cp3)
  758. X            *cp2++ = *cp1++;
  759. X    }
  760. X#if    REVSTA
  761. X    TTrev(FALSE);
  762. X#endif
  763. X    vp1->v_flag &= ~VFCHG;        /* flag this line as updated */
  764. X    return(TRUE);
  765. X#endif
  766. X}
  767. X#endif
  768. X
  769. X/*
  770. X * Redisplay the mode line for the window pointed to by the "wp". This is the
  771. X * only routine that has any idea of how the modeline is formatted. You can
  772. X * change the modeline format by hacking at this routine. Called by "update"
  773. X * any time there is a dirty window.
  774. X */
  775. Xmodeline(wp)
  776. X    WINDOW *wp;
  777. X{
  778. X    register char *cp;
  779. X    register int c;
  780. X    register int n;        /* cursor position count */
  781. X    register BUFFER *bp;
  782. X    register int i;        /* loop index */
  783. X    register int lchar;        /* character to draw line in buffer with */
  784. X    register int firstm;    /* is this the first mode? */
  785. X    char tline[NLINE];        /* buffer for part of mode line */
  786. X
  787. X    n = wp->w_toprow+wp->w_ntrows;          /* Location. */
  788. X    vscreen[n]->v_flag |= VFCHG | VFREQ | VFCOL;/* Redraw next time. */
  789. X#if    COLOR
  790. X    vscreen[n]->v_rfcolor = 0;            /* black on */
  791. X    vscreen[n]->v_rbcolor = 7;            /* white.....*/
  792. X#endif
  793. X    vtmove(n, 0);                           /* Seek to right line. */
  794. X    if (wp == curwp)                /* mark the current buffer */
  795. X    lchar = '=';
  796. X    else
  797. X#if    REVSTA
  798. X    if (revexist)
  799. X        lchar = ' ';
  800. X    else
  801. X#endif
  802. X        lchar = '-';
  803. X
  804. X    bp = wp->w_bufp;
  805. X    if ((bp->b_flag&BFTRUNC) != 0)
  806. X    vtputc('#');
  807. X    else
  808. X    vtputc(lchar);
  809. X
  810. X    if ((bp->b_flag&BFCHG) != 0)                /* "*" if changed. */
  811. X        vtputc('*');
  812. X    else
  813. X        vtputc(lchar);
  814. X
  815. X    n  = 2;
  816. X    strcpy(tline, " ");                /* Buffer name. */
  817. X    strcat(tline, PROGNAME);
  818. X    strcat(tline, " ");
  819. X    strcat(tline, VERSION);
  820. X    strcat(tline, " (");
  821. X
  822. X    /* display the modes */
  823. X
  824. X    firstm = TRUE;
  825. X    for (i = 0; i < NUMMODES; i++)    /* add in the mode flags */
  826. X        if (wp->w_bufp->b_mode & (1 << i)) {
  827. X            if (firstm != TRUE)
  828. X                strcat(tline, " ");
  829. X            firstm = FALSE;
  830. X            strcat(tline, modename[i]);
  831. X        }
  832. X    strcat(tline,") ");
  833. X
  834. X    cp = &tline[0];
  835. X    while ((c = *cp++) != 0)
  836. X        {
  837. X        vtputc(c);
  838. X        ++n;
  839. X        }
  840. X
  841. X#if 0
  842. X    vtputc(lchar);
  843. X    vtputc((wp->w_flag&WFCOLR) != 0  ? 'C' : lchar);
  844. X    vtputc((wp->w_flag&WFMODE) != 0  ? 'M' : lchar);
  845. X    vtputc((wp->w_flag&WFHARD) != 0  ? 'H' : lchar);
  846. X    vtputc((wp->w_flag&WFEDIT) != 0  ? 'E' : lchar);
  847. X    vtputc((wp->w_flag&WFMOVE) != 0  ? 'V' : lchar);
  848. X    vtputc((wp->w_flag&WFFORCE) != 0 ? 'F' : lchar);
  849. X    vtputc(lchar);
  850. X    n += 8;
  851. X#endif
  852. X
  853. X    vtputc(lchar);
  854. X    vtputc(lchar);
  855. X    vtputc(' ');
  856. X    n += 3;
  857. X    cp = &bp->b_bname[0];
  858. X
  859. X    while ((c = *cp++) != 0)
  860. X        {
  861. X        vtputc(c);
  862. X        ++n;
  863. X        }
  864. X
  865. X    vtputc(' ');
  866. X    vtputc(lchar);
  867. X    vtputc(lchar);
  868. X    n += 3;
  869. X
  870. X    if (bp->b_fname[0] != 0)            /* File name. */
  871. X        {
  872. X    vtputc(' ');
  873. X    ++n;
  874. X        cp = "File: ";
  875. X
  876. X        while ((c = *cp++) != 0)
  877. X            {
  878. X            vtputc(c);
  879. X            ++n;
  880. X            }
  881. X
  882. X        cp = &bp->b_fname[0];
  883. X
  884. X        while ((c = *cp++) != 0)
  885. X            {
  886. X            vtputc(c);
  887. X            ++n;
  888. X            }
  889. X
  890. X        vtputc(' ');
  891. X        ++n;
  892. X        }
  893. X
  894. X    while (n < term.t_ncol)             /* Pad to full width. */
  895. X        {
  896. X        vtputc(lchar);
  897. X        ++n;
  898. X        }
  899. X}
  900. X
  901. Xupmode()    /* update all the mode lines */
  902. X
  903. X{
  904. X    register WINDOW *wp;
  905. X
  906. X    wp = wheadp;
  907. X    while (wp != NULL) {
  908. X        wp->w_flag |= WFMODE;
  909. X        wp = wp->w_wndp;
  910. X    }
  911. X}
  912. X
  913. X/*
  914. X * Send a command to the terminal to move the hardware cursor to row "row"
  915. X * and column "col". The row and column arguments are origin 0. Optimize out
  916. X * random calls. Update "ttrow" and "ttcol".
  917. X */
  918. Xmovecursor(row, col)
  919. X    {
  920. X    if (row!=ttrow || col!=ttcol)
  921. X        {
  922. X        ttrow = row;
  923. X        ttcol = col;
  924. X        TTmove(row, col);
  925. X        }
  926. X    }
  927. X
  928. X/*
  929. X * Erase the message line. This is a special routine because the message line
  930. X * is not considered to be part of the virtual screen. It always works
  931. X * immediately; the terminal buffer is flushed via a call to the flusher.
  932. X */
  933. Xmlerase()
  934. X    {
  935. X    int i;
  936. X    
  937. X    movecursor(term.t_nrow, 0);
  938. X    if (discmd == FALSE)
  939. X        return;
  940. X
  941. X#if    COLOR
  942. X     TTforg(7);
  943. X     TTbacg(0);
  944. X#endif
  945. X    if (eolexist == TRUE)
  946. X        TTeeol();
  947. X    else {
  948. X        for (i = 0; i < term.t_ncol - 1; i++)
  949. X            TTputc(' ');
  950. X        movecursor(term.t_nrow, 1);    /* force the move! */
  951. X        movecursor(term.t_nrow, 0);
  952. X    }
  953. X    TTflush();
  954. X    mpresf = FALSE;
  955. X    }
  956. X
  957. X/*
  958. X * Write a message into the message line. Keep track of the physical cursor
  959. X * position. A small class of printf like format items is handled. Assumes the
  960. X * stack grows down; this assumption is made by the "++" in the argument scan
  961. X * loop. Set the "message line" flag TRUE.
  962. X */
  963. X
  964. Xmlwrite(fmt, arg)
  965. X
  966. Xchar *fmt;    /* format string for output */
  967. Xchar *arg;    /* pointer to first argument to print */
  968. X
  969. X{
  970. X    register int c;        /* current char in format string */
  971. X    register char *ap;    /* ptr to current data field */
  972. X
  973. X    /* if we are not currently echoing on the command line, abort this */
  974. X    if (discmd == FALSE) {
  975. X        movecursor(term.t_nrow, 0);
  976. X        return;
  977. X    }
  978. X
  979. X#if    COLOR
  980. X    /* set up the proper colors for the command line */
  981. X    TTforg(7);
  982. X    TTbacg(0);
  983. X#endif
  984. X
  985. X    /* if we can not erase to end-of-line, do it manually */
  986. X    if (eolexist == FALSE) {
  987. X        mlerase();
  988. X        TTflush();
  989. X    }
  990. X
  991. X    movecursor(term.t_nrow, 0);
  992. X    ap = (char *) &arg;
  993. X    while ((c = *fmt++) != 0) {
  994. X        if (c != '%') {
  995. X            TTputc(c);
  996. X            ++ttcol;
  997. X        } else {
  998. X            c = *fmt++;
  999. X            switch (c) {
  1000. X                case 'd':
  1001. X                    mlputi(*(int *)ap, 10);
  1002. X                    ap += sizeof(int);
  1003. X                    break;
  1004. X
  1005. X                case 'o':
  1006. X                    mlputi(*(int *)ap,  8);
  1007. X                    ap += sizeof(int);
  1008. X                    break;
  1009. X
  1010. X                case 'x':
  1011. X                    mlputi(*(int *)ap, 16);
  1012. X                    ap += sizeof(int);
  1013. X                    break;
  1014. X
  1015. X                case 'D':
  1016. X                    mlputli(*(long *)ap, 10);
  1017. X                    ap += sizeof(long);
  1018. X                    break;
  1019. X
  1020. X                case 's':
  1021. X                    mlputs(*(char **)ap);
  1022. X                    ap += sizeof(char *);
  1023. X                    break;
  1024. X
  1025. X                case 'f':
  1026. X                    mlputf(*(int *)ap);
  1027. X                    ap += sizeof(int);
  1028. X                    break;
  1029. X
  1030. X                default:
  1031. X                    TTputc(c);
  1032. X                    ++ttcol;
  1033. X            }
  1034. X        }
  1035. X    }
  1036. X
  1037. X    /* if we can, erase to the end of screen */
  1038. X    if (eolexist == TRUE)
  1039. X        TTeeol();
  1040. X    TTflush();
  1041. X    mpresf = TRUE;
  1042. X}
  1043. X
  1044. X/*    Force a string out to the message line regardless of the
  1045. X    current $discmd setting. This is needed when $debug is TRUE
  1046. X    and for the write-message and clear-message-line commands
  1047. X*/
  1048. X
  1049. Xmlforce(s)
  1050. X
  1051. Xchar *s;    /* string to force out */
  1052. X
  1053. X{
  1054. X    register int oldcmd;    /* original command display flag */
  1055. X
  1056. X    oldcmd = discmd;    /* save the discmd value */
  1057. X    discmd = TRUE;        /* and turn display on */
  1058. X    mlwrite(s);        /* write the string out */
  1059. X    discmd = oldcmd;    /* and restore the original setting */
  1060. X}
  1061. X
  1062. X/*
  1063. X * Write out a string. Update the physical cursor position. This assumes that
  1064. X * the characters in the string all have width "1"; if this is not the case
  1065. X * things will get screwed up a little.
  1066. X */
  1067. Xmlputs(s)
  1068. X    char *s;
  1069. X    {
  1070. X    register int c;
  1071. X
  1072. X    while ((c = *s++) != 0)
  1073. X        {
  1074. X        TTputc(c);
  1075. X        ++ttcol;
  1076. X        }
  1077. X    }
  1078. X
  1079. X/*
  1080. X * Write out an integer, in the specified radix. Update the physical cursor
  1081. X * position.
  1082. X */
  1083. Xmlputi(i, r)
  1084. X    {
  1085. X    register int q;
  1086. X    static char hexdigits[] = "0123456789ABCDEF";
  1087. X
  1088. X    if (i < 0)
  1089. X        {
  1090. X        i = -i;
  1091. X        TTputc('-');
  1092. X        }
  1093. X
  1094. X    q = i/r;
  1095. X
  1096. X    if (q != 0)
  1097. X        mlputi(q, r);
  1098. X
  1099. X    TTputc(hexdigits[i%r]);
  1100. X    ++ttcol;
  1101. X    }
  1102. X
  1103. X/*
  1104. X * do the same except as a long integer.
  1105. X */
  1106. Xmlputli(l, r)
  1107. X    long l;
  1108. X    {
  1109. X    register long q;
  1110. X
  1111. X    if (l < 0)
  1112. X        {
  1113. X        l = -l;
  1114. X        TTputc('-');
  1115. X        }
  1116. X
  1117. X    q = l/r;
  1118. X
  1119. X    if (q != 0)
  1120. X        mlputli(q, r);
  1121. X
  1122. X    TTputc((int)(l%r)+'0');
  1123. X    ++ttcol;
  1124. X    }
  1125. X
  1126. X/*
  1127. X *    write out a scaled integer with two decimal places
  1128. X */
  1129. X
  1130. Xmlputf(s)
  1131. X
  1132. Xint s;    /* scaled integer to output */
  1133. X
  1134. X{
  1135. X    int i;    /* integer portion of number */
  1136. X    int f;    /* fractional portion of number */
  1137. X
  1138. X    /* break it up */
  1139. X    i = s / 100;
  1140. X    f = s % 100;
  1141. X
  1142. X    /* send out the integer portion */
  1143. X    mlputi(i, 10);
  1144. X    TTputc('.');
  1145. X    TTputc((f / 10) + '0');
  1146. X    TTputc((f % 10) + '0');
  1147. X    ttcol += 3;
  1148. X}    
  1149. X
  1150. X#if RAINBOW
  1151. X
  1152. Xputline(row, col, buf)
  1153. X    int row, col;
  1154. X    char buf[];
  1155. X    {
  1156. X    int n;
  1157. X
  1158. X    n = strlen(buf);
  1159. X    if (col + n - 1 > term.t_ncol)
  1160. X        n = term.t_ncol - col + 1;
  1161. X    Put_Data(row, col, n, buf);
  1162. X    }
  1163. X#endif
  1164. X
  1165. FRIDAY_NIGHT
  1166. echo mes.3 completed!
  1167. # That's all folks!
  1168.  
  1169.  
  1170.