home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3493 < prev    next >
Encoding:
Internet Message Format  |  1991-06-20  |  54.5 KB

  1. From: pgf@cayman.COM (Paul Fox)
  2. Newsgroups: alt.sources
  3. Subject: Vile 03/17 - vi feel-alike (multi-window)
  4. Message-ID: <4522@cayman.COM>
  5. Date: 7 Jun 91 22:09:16 GMT
  6.  
  7. #!/bin/sh
  8. # this is vileshar.03 (part 3 of Vile)
  9. # do not concatenate these parts, unpack them in order with /bin/sh
  10. # file crypt.c continued
  11. #
  12. if test ! -r _shar_seq_.tmp; then
  13.     echo 'Please unpack part 1 first!'
  14.     exit 1
  15. fi
  16. (read Scheck
  17.  if test "$Scheck" != 3; then
  18.     echo Please unpack part "$Scheck" next!
  19.     exit 1
  20.  else
  21.     exit 0
  22.  fi
  23. ) < _shar_seq_.tmp || exit 1
  24. echo 'x - continuing file crypt.c'
  25. sed 's/^X//' << 'SHAR_EOF' >> 'crypt.c' &&
  26. X *        file from one computer should be able to be decrypted 
  27. X *        on another computer.
  28. X *
  29. X *        3.    The encryption had to be inexpensive, both in terms
  30. X *        of speed and space.
  31. X *
  32. X *        4.    The system needed to be secure against all but the
  33. X *        most determined of attackers.
  34. X *
  35. X *    For encryption of a block of data, one calls crypt passing 
  36. X *    a pointer to the data block and its length. The data block is 
  37. X *    encrypted in place, that is, the encrypted output overwrites 
  38. X *    the input.  Decryption is totally isomorphic, and is performed 
  39. X *    in the same manner by the same routine.  
  40. X *
  41. X *    Before using this routine for encrypting data, you are expected 
  42. X *    to specify an encryption key.  This key is an arbitrary string,
  43. X *    to be supplied by the user.  To set the key takes two calls to 
  44. X *    crypt().  First, you call 
  45. X *
  46. X *        crypt(NULL, vector)
  47. X *
  48. X *    This resets all internal control information.  Typically (and 
  49. X *    specifically in the case on MICRO-emacs) you would use a "vector" 
  50. X *    of 0.  Other values can be used to customize your editor to be 
  51. X *    "incompatable" with the normally distributed version.  For 
  52. X *    this purpose, the best results will be obtained by avoiding
  53. X *    multiples of 95.
  54. X *
  55. X *    Then, you "encrypt" your password by calling 
  56. X *
  57. X *        crypt(pass, strlen(pass))
  58. X *
  59. X *    where "pass" is your password string.  Crypt() will destroy 
  60. X *    the original copy of the password (it becomes encrypted), 
  61. X *    which is good.  You do not want someone on a multiuser system 
  62. X *    to peruse your memory space and bump into your password.  
  63. X *    Still, it is a better idea to erase the password buffer to 
  64. X *    defeat memory perusal by a more technical snooper.  
  65. X *
  66. X *    For the interest of cryptologists, at the heart of this 
  67. X *    function is a Beaufort Cipher.  The cipher alphabet is the 
  68. X *    range of printable characters (' ' to '~'), all "control" 
  69. X *    and "high-bit" characters are left unaltered.
  70. X *
  71. X *    The key is a variant autokey, derived from a wieghted sum 
  72. X *    of all the previous clear text and cipher text.  A counter 
  73. X *    is used as salt to obiterate any simple cyclic behavior 
  74. X *    from the clear text, and key feedback is used to assure 
  75. X *    that the entire message is based on the original key, 
  76. X *    preventing attacks on the last part of the message as if 
  77. X *    it were a pure autokey system.
  78. X *
  79. X *    Overall security of encrypted data depends upon three 
  80. X *    factors:  the fundamental cryptographic system must be 
  81. X *    difficult to compromise; exhaustive searching of the key 
  82. X *    space must be computationally expensive; keys and plaintext 
  83. X *    must remain out of sight.  This system satisfies this set
  84. X *    of conditions to within the degree desired for MicroEMACS.
  85. X *
  86. X *    Though direct methods of attack (against systems such as 
  87. X *    this) do exist, they are not well known and will consume 
  88. X *    considerable amounts of computing time.  An exhaustive
  89. X *    search requires over a billion investigations, on average.
  90. X *
  91. X *    The choice, entry, storage, manipulation, alteration, 
  92. X *    protection and security of the keys themselves are the 
  93. X *    responsiblity of the user.  
  94. X *
  95. X **********/
  96. X
  97. crypt(bptr, len)
  98. register char *bptr;    /* buffer of characters to be encrypted */
  99. register int len;    /* number of characters in the buffer */
  100. {
  101. X    register int cc;    /* current character being considered */
  102. X
  103. X    static long key = 0;    /* 29 bit encipherment key */
  104. X    static int salt = 0;    /* salt to spice up key with */
  105. X
  106. X    if (!bptr) {        /* is there anything here to encrypt? */
  107. X        key = len;    /* set the new key */
  108. X        salt = len;    /* set the new salt */
  109. X        return;
  110. X    }
  111. X    while (len--) {        /* for every character in the buffer */
  112. X
  113. X        cc = *bptr;    /* get a character out of the buffer */
  114. X
  115. X        /* only encipher printable characters */
  116. X        if ((cc >= ' ') && (cc <= '~')) {
  117. X
  118. /**  If the upper bit (bit 29) is set, feed it back into the key.  This 
  119. X    assures us that the starting key affects the entire message.  **/
  120. X
  121. X            key &= 0x1FFFFFFFL;    /* strip off overflow */
  122. X            if (key & 0x10000000L) {
  123. X                key ^= 0x0040A001L;    /* feedback */
  124. X            }
  125. X
  126. /**  Down-bias the character, perform a Beaufort encipherment, and 
  127. X    up-bias the character again.  We want key to be positive 
  128. X    so that the left shift here will be more portable and the 
  129. X    mod95() faster   **/
  130. X
  131. X            cc = mod95((int)(key % 95) - (cc - ' ')) + ' ';
  132. X
  133. /**  the salt will spice up the key a little bit, helping to obscure 
  134. X    any patterns in the clear text, particularly when all the 
  135. X    characters (or long sequences of them) are the same.  We do 
  136. X    not want the salt to go negative, or it will affect the key 
  137. X    too radically.  It is always a good idea to chop off cyclics 
  138. X    to prime values.  **/
  139. X
  140. X            if (++salt >= 20857) {    /* prime modulus */
  141. X                salt = 0;
  142. X            }
  143. X
  144. /**  our autokey (a special case of the running key) is being 
  145. X    generated by a wieghted checksum of clear text, cipher 
  146. X    text, and salt.   **/
  147. X
  148. X            key = key + key + cc + *bptr + salt;
  149. X        }
  150. X        *bptr++ = cc;    /* put character back into buffer */
  151. X    }
  152. X    return;
  153. }
  154. X
  155. static int mod95(val)
  156. X
  157. register int val;
  158. X
  159. {
  160. X    /*  The mathematical MOD does not match the computer MOD  */
  161. X
  162. X    /*  Yes, what I do here may look strange, but it gets the
  163. X        job done, and portably at that.  */
  164. X
  165. X    while (val >= 9500)
  166. X        val -= 9500;
  167. X    while (val >= 950)
  168. X        val -= 950;
  169. X    while (val >= 95)
  170. X        val -= 95;
  171. X    while (val < 0)
  172. X        val += 95;
  173. X    return (val);
  174. }
  175. #else
  176. nocrypt()
  177. {
  178. }
  179. #endif
  180. SHAR_EOF
  181. echo 'File crypt.c is complete' &&
  182. chmod 0444 crypt.c ||
  183. echo 'restore of crypt.c failed'
  184. Wc_c="`wc -c < 'crypt.c'`"
  185. test 6989 -eq "$Wc_c" ||
  186.     echo 'crypt.c: original size 6989, current size' "$Wc_c"
  187. # ============= csrch.c ==============
  188. echo 'x - extracting csrch.c (Text)'
  189. sed 's/^X//' << 'SHAR_EOF' > 'csrch.c' &&
  190. X
  191. #include "estruct.h"
  192. #include "edef.h"
  193. X
  194. /* These functions perform vi's on-this-line character scanning functions.
  195. X    written for vile by Paul Fox, (c)1990
  196. */
  197. static short lastscan;
  198. static short lastchar;
  199. #define BACK 0
  200. #define FORW 1
  201. #define DIREC 1
  202. X
  203. #define F 0
  204. #define T 2
  205. #define TYPE 2
  206. X
  207. X
  208. fscan(f,n,c)
  209. {
  210. X    int i = 0;
  211. X    int doto;
  212. X
  213. X    if (n <= 0) n = 1;
  214. X
  215. X    lastchar = c;
  216. X    lastscan = FORW;
  217. X
  218. X    doto = curwp->w_doto;
  219. X
  220. X    i = doto+1;
  221. X    while(i < llength(curwp->w_dotp)) {
  222. X        if ( c == lgetc(curwp->w_dotp,i)) {
  223. X            doto = i;
  224. X            n--;
  225. X            if (!n) break;
  226. X        }
  227. X        i++;
  228. X    }
  229. X
  230. X    if ( i == llength(curwp->w_dotp)) {
  231. X        TTbeep();
  232. X        return(FALSE);
  233. X    }
  234. X    if (doingopcmd)
  235. X        doto++;
  236. X
  237. X    curwp->w_doto = doto;
  238. X    curwp->w_flag |= WFMOVE;
  239. X    return(TRUE);
  240. X            
  241. }
  242. X
  243. bscan(f,n,c)
  244. {
  245. X    int i = 0;
  246. X    int doto;
  247. X
  248. X    if (n <= 0) n = 1;
  249. X
  250. X    lastchar = c;
  251. X    lastscan = BACK;
  252. X
  253. X    doto = curwp->w_doto;
  254. X
  255. X    i = doto-1;
  256. X    while(i >= 0) {
  257. X        if ( c == lgetc(curwp->w_dotp,i)) {
  258. X            doto = i;
  259. X            n--;
  260. X            if (!n) break;
  261. X        }
  262. X        i--;
  263. X    }
  264. X
  265. X    if ( i < 0 ) {
  266. X        TTbeep();
  267. X        return(FALSE);
  268. X    }
  269. X
  270. X    curwp->w_doto = doto;
  271. X    curwp->w_flag |= WFMOVE;
  272. X    return(TRUE);
  273. X
  274. }
  275. X
  276. /* f */
  277. fcsrch(f,n)
  278. {
  279. X    register int c;
  280. X
  281. X        c = kbd_key();
  282. X    if (c == quotec)
  283. X        c = tgetc();
  284. X    else if (c == abortc)
  285. X        return FALSE;
  286. X    else
  287. X        c = kcod2key(c);
  288. X
  289. X    return(fscan(f,n,c));
  290. }
  291. X
  292. /* F */
  293. bcsrch(f,n)
  294. {
  295. X    register int c;
  296. X
  297. X        c = kbd_key();
  298. X    if (c == quotec)
  299. X        c = tgetc();
  300. X    else if (c == abortc)
  301. X        return FALSE;
  302. X    else
  303. X        c = kcod2key(c);
  304. X
  305. X    return(bscan(f,n,c));
  306. }
  307. X
  308. /* t */
  309. fcsrch_to(f,n)
  310. {
  311. X    int s;
  312. X    s = fcsrch(f,n);
  313. X    if (s == TRUE)
  314. X        s = backchar(FALSE,1);
  315. X    lastscan |= T;
  316. X    return(s);
  317. }
  318. X
  319. /* T */
  320. bcsrch_to(f,n)
  321. {
  322. X    int s;
  323. X    s = bcsrch(f,n);
  324. X    if (s == TRUE)
  325. X        s = forwchar(FALSE,1);
  326. X    lastscan |= T;
  327. X    return(s);
  328. }
  329. X
  330. /* ; */
  331. rep_csrch(f,n)
  332. {
  333. X    int s;
  334. X    int ls = lastscan;
  335. X
  336. X    if ((ls & DIREC) == FORW) {
  337. X        s = fscan(f,n,lastchar);
  338. X        if ((ls & TYPE) == T) {
  339. X            if (s == TRUE)
  340. X                s = backchar(FALSE,1);
  341. X            lastscan |= T;
  342. X        }
  343. X        return(s);
  344. X    } else {
  345. X        s = bscan(f,n,lastchar);
  346. X        if ((ls & TYPE) == T) {
  347. X            if (s == TRUE)
  348. X                s = forwchar(FALSE,1);
  349. X            lastscan |= T;
  350. X        }
  351. X        return(s);
  352. X    }
  353. }
  354. X
  355. /* , */
  356. rev_csrch(f,n)
  357. {
  358. X    int s;
  359. X
  360. X    lastscan ^= DIREC;
  361. X    s = rep_csrch(f,n);
  362. X    lastscan ^= DIREC;
  363. X    return(s);
  364. }
  365. SHAR_EOF
  366. chmod 0444 csrch.c ||
  367. echo 'restore of csrch.c failed'
  368. Wc_c="`wc -c < 'csrch.c'`"
  369. test 2171 -eq "$Wc_c" ||
  370.     echo 'csrch.c: original size 2171, current size' "$Wc_c"
  371. # ============= dg10.c ==============
  372. echo 'x - extracting dg10.c (Text)'
  373. sed 's/^X//' << 'SHAR_EOF' > 'dg10.c' &&
  374. /*
  375. X * The routines in this file provide support for the Data General Model 10
  376. X * Microcomputer.
  377. X */
  378. X
  379. #define    termdef    1            /* don't define "term" external */
  380. X
  381. #include        <stdio.h>
  382. #include    "estruct.h"
  383. #include        "edef.h"
  384. X
  385. #if     DG10
  386. X
  387. #define NROW    24                      /* Screen size.                 */
  388. #define NCOL    80                      /* Edit if you want to.         */
  389. #define    NPAUSE    100            /* # times thru update to pause */
  390. #define    MARGIN    8            /* size of minimim margin and    */
  391. #define    SCRSIZ    64            /* scroll size for extended lines */
  392. #define BEL     0x07                    /* BEL character.               */
  393. #define ESC     30                      /* DG10 ESC character.          */
  394. X
  395. extern  int     ttopen();               /* Forward references.          */
  396. extern  int     ttgetc();
  397. extern  int     ttputc();
  398. extern  int     ttflush();
  399. extern  int     ttclose();
  400. extern    int    dg10kopen();
  401. extern    int    dg10kclose();
  402. extern  int     dg10move();
  403. extern  int     dg10eeol();
  404. extern  int     dg10eeop();
  405. extern  int     dg10beep();
  406. extern  int     dg10open();
  407. extern    int    dg10rev();
  408. extern    int    dg10close();
  409. extern    int    dg10cres();
  410. X
  411. #if    COLOR
  412. extern    int    dg10fcol();
  413. extern    int    dg10bcol();
  414. X
  415. int    cfcolor = -1;        /* current forground color */
  416. int    cbcolor = -1;        /* current background color */
  417. int    ctrans[] = {        /* emacs -> DG10 color translation table */
  418. X    0, 4, 2, 6, 1, 5, 3, 7};
  419. #endif
  420. X
  421. /*
  422. X * Standard terminal interface dispatch table. Most of the fields point into
  423. X * "termio" code.
  424. X */
  425. TERM    term    = {
  426. X    NROW-1,
  427. X        NROW-1,
  428. X        NCOL,
  429. X        NCOL,
  430. X    MARGIN,
  431. X    SCRSIZ,
  432. X    NPAUSE,
  433. X        dg10open,
  434. X        dg10close,
  435. X    dg10kopen,
  436. X    dg10kclose,
  437. X        ttgetc,
  438. X        ttputc,
  439. X        ttflush,
  440. X        dg10move,
  441. X        dg10eeol,
  442. X        dg10eeop,
  443. X        dg10beep,
  444. X    dg10rev,
  445. X    dg10cres
  446. #if    COLOR
  447. X    , dg10fcol,
  448. X    dg10bcol
  449. #endif
  450. };
  451. X
  452. #if    COLOR
  453. dg10fcol(color)        /* set the current output color */
  454. X
  455. int color;    /* color to set */
  456. X
  457. {
  458. X    if (color == cfcolor)
  459. X        return;
  460. X    ttputc(ESC);
  461. X    ttputc(0101);
  462. X    ttputc(ctrans[color]);
  463. X    cfcolor = color;
  464. }
  465. X
  466. dg10bcol(color)        /* set the current background color */
  467. X
  468. int color;    /* color to set */
  469. X
  470. {
  471. X    if (color == cbcolor)
  472. X        return;
  473. X    ttputc(ESC);
  474. X    ttputc(0102);
  475. X    ttputc(ctrans[color]);
  476. X        cbcolor = color;
  477. }
  478. #endif
  479. X
  480. dg10move(row, col)
  481. {
  482. X    ttputc(16);
  483. X        ttputc(col);
  484. X    ttputc(row);
  485. }
  486. X
  487. dg10eeol()
  488. {
  489. X        ttputc(11);
  490. }
  491. X
  492. dg10eeop()
  493. {
  494. #if    COLOR
  495. X    dg10fcol(gfcolor);
  496. X    dg10bcol(gbcolor);
  497. #endif
  498. X        ttputc(ESC);
  499. X        ttputc(0106);
  500. X        ttputc(0106);
  501. }
  502. X
  503. dg10rev(state)        /* change reverse video state */
  504. X
  505. int state;    /* TRUE = reverse, FALSE = normal */
  506. X
  507. {
  508. #if    COLOR
  509. X    if (state == TRUE) {
  510. X        dg10fcol(0);
  511. X        dg10bcol(7);
  512. X    }
  513. #else
  514. X    ttputc(ESC);
  515. X    ttputc(state ? 0104: 0105);
  516. #endif
  517. }
  518. X
  519. dg10cres()    /* change screen resolution */
  520. X
  521. {
  522. X    return(TRUE);
  523. }
  524. X
  525. spal()        /* change palette string */
  526. X
  527. {
  528. X    /*    Does nothing here    */
  529. }
  530. X
  531. dg10beep()
  532. {
  533. X        ttputc(BEL);
  534. X        ttflush();
  535. }
  536. X
  537. dg10open()
  538. {
  539. X    strcpy(sres, "NORMAL");
  540. X    revexist = TRUE;
  541. X        ttopen();
  542. }
  543. X
  544. dg10close()
  545. X
  546. {
  547. #if    COLOR
  548. X    dg10fcol(7);
  549. X    dg10bcol(0);
  550. #endif
  551. X    ttclose();
  552. }
  553. X
  554. dg10kopen()
  555. X
  556. {
  557. }
  558. X
  559. dg10kclose()
  560. X
  561. {
  562. }
  563. X
  564. #if    FLABEL
  565. fnclabel(f, n)        /* label a function key */
  566. X
  567. int f,n;    /* default flag, numeric argument [unused] */
  568. X
  569. {
  570. X    /* on machines with no function keys...don't bother */
  571. X    return(TRUE);
  572. }
  573. #endif
  574. #else
  575. dg10hello()
  576. {
  577. }
  578. #endif
  579. SHAR_EOF
  580. chmod 0444 dg10.c ||
  581. echo 'restore of dg10.c failed'
  582. Wc_c="`wc -c < 'dg10.c'`"
  583. test 3333 -eq "$Wc_c" ||
  584.     echo 'dg10.c: original size 3333, current size' "$Wc_c"
  585. # ============= display.c ==============
  586. echo 'x - extracting display.c (Text)'
  587. sed 's/^X//' << 'SHAR_EOF' > 'display.c' &&
  588. /*
  589. X * The functions in this file handle redisplay. There are two halves, the
  590. X * ones that update the virtual display screen, and the ones that make the
  591. X * physical display screen the same as the virtual display screen. These
  592. X * functions use hints that are left in the windows by the commands.
  593. X *
  594. X */
  595. X
  596. X
  597. #include        <stdio.h>
  598. #include        <varargs.h>
  599. #include    "estruct.h"
  600. #include        "edef.h"
  601. #if UNIX
  602. #include <signal.h>
  603. #include <termio.h>
  604. #if ODT
  605. #include <sys/types.h>
  606. #include <sys/stream.h>
  607. #include <sys/ptem.h>
  608. #endif
  609. #endif
  610. X
  611. typedef struct  VIDEO {
  612. X        int    v_flag;                 /* Flags */
  613. #if    COLOR
  614. X    int    v_fcolor;        /* current forground color */
  615. X    int    v_bcolor;        /* current background color */
  616. X    int    v_rfcolor;        /* requested forground color */
  617. X    int    v_rbcolor;        /* requested background color */
  618. #endif
  619. X    /* allocate 4 bytes here, and malloc 4 bytes less than we need,
  620. X        to keep malloc from rounding up. */
  621. X        char    v_text[4];              /* Screen data. */
  622. }       VIDEO;
  623. X
  624. #define VFCHG   0x0001                  /* Changed flag            */
  625. #define    VFEXT    0x0002            /* extended (beyond column 80)    */
  626. #define    VFREV    0x0004            /* reverse video status        */
  627. #define    VFREQ    0x0008            /* reverse video request    */
  628. #define    VFCOL    0x0010            /* color change requested    */
  629. X
  630. VIDEO   **vscreen;                      /* Virtual screen. */
  631. #if    ! MEMMAP
  632. VIDEO   **pscreen;                      /* Physical screen. */
  633. #endif
  634. X
  635. X
  636. int displaying = FALSE;
  637. #ifdef SIGWINCH
  638. /* for window size changes */
  639. int chg_width, chg_height;
  640. #endif
  641. X
  642. /*
  643. X * Initialize the data structures used by the display code. The edge vectors
  644. X * used to access the screens are set up. The operating system's terminal I/O
  645. X * channel is set up. All the other things get initialized at compile time.
  646. X * The original window has "WFCHG" set, so that it will get completely
  647. X * redrawn on the first call to "update".
  648. X */
  649. vtinit()
  650. {
  651. X    register int i;
  652. X    register VIDEO *vp;
  653. X
  654. X    TTopen();        /* open the screen */
  655. X    TTkopen();        /* open the keyboard */
  656. X    TTrev(FALSE);
  657. X    vscreen = (VIDEO **) malloc(term.t_mrow*sizeof(VIDEO *));
  658. X
  659. X    if (vscreen == NULL)
  660. X        exit(1);
  661. X
  662. #if    ! MEMMAP
  663. X    pscreen = (VIDEO **) malloc(term.t_mrow*sizeof(VIDEO *));
  664. X
  665. X    if (pscreen == NULL)
  666. X        exit(1);
  667. #endif
  668. X
  669. X    for (i = 0; i < term.t_mrow; ++i) {
  670. X        /* struct VIDEO already has 4 of the bytes */
  671. X        vp = (VIDEO *) malloc(sizeof(struct VIDEO) + term.t_mcol - 4);
  672. X
  673. X        if (vp == NULL)
  674. X            exit(1);
  675. X
  676. X    vp->v_flag = 0;
  677. #if    COLOR
  678. X    vp->v_rfcolor = 7;
  679. X    vp->v_rbcolor = 0;
  680. #endif
  681. X        vscreen[i] = vp;
  682. #if    ! MEMMAP
  683. X        /* struct VIDEO already has 4 of the bytes */
  684. X        vp = (VIDEO *) malloc(sizeof(struct VIDEO) + term.t_mcol - 4);
  685. X
  686. X        if (vp == NULL)
  687. X            exit(1);
  688. X
  689. X    vp->v_flag = 0;
  690. X        pscreen[i] = vp;
  691. #endif
  692. X        }
  693. }
  694. X
  695. /*
  696. X * Clean up the virtual terminal system, in anticipation for a return to the
  697. X * operating system. Move down to the last line and advance, to make room
  698. X * for the system prompt. Shut down the channel to the
  699. X * terminal.
  700. X */
  701. vttidy(f)
  702. {
  703. X    ttclean(f);    /* does it all now */
  704. }
  705. X
  706. /*
  707. X * Set the virtual cursor to the specified row and column on the virtual
  708. X * screen. There is no checking for nonsense values.
  709. X */
  710. vtmove(row, col)
  711. {
  712. X    vtrow = row;
  713. X    vtcol = col;
  714. }
  715. X
  716. /* Write a character to the virtual screen. The virtual row and
  717. X   column are updated. If we are not yet on left edge, don't print
  718. X   it yet. If the line is too long put a ">" in the last column.
  719. X   This routine only puts printing characters into the virtual
  720. X   terminal buffers. Only column overflow is checked.
  721. */
  722. X
  723. vtputc(c,list)
  724. int c,list;
  725. {
  726. X    register VIDEO *vp;    /* ptr to line being updated */
  727. X
  728. X    vp = vscreen[vtrow];
  729. X
  730. X    if (c == '\t' && !list) {
  731. X        do {
  732. X            vtputc(' ',FALSE);
  733. X        } while (((vtcol + taboff)&TABMASK) != 0);
  734. X    } else if (c == '\n' && !list) {
  735. X        return;
  736. X    } else if (vtcol >= term.t_ncol) {
  737. X        ++vtcol;
  738. X        vp->v_text[term.t_ncol - 1] = '>';
  739. X    } else if (!isprint(c)) {
  740. X        vtputc('^',FALSE);
  741. X        vtputc(toalpha(c),FALSE);
  742. X    } else {
  743. X        if (vtcol >= 0)
  744. X            vp->v_text[vtcol] = c;
  745. X        ++vtcol;
  746. X    }
  747. }
  748. X
  749. vtgetc(col)
  750. {
  751. X    return vscreen[vtrow]->v_text[col];
  752. }
  753. X
  754. vtputsn(s,n)
  755. char *s;
  756. {
  757. X    int c;
  758. X    while (n-- && (c = *s++) != 0)
  759. X        vtputc(c,FALSE);
  760. }
  761. X
  762. /*
  763. X * Erase from the end of the software cursor to the end of the line on which
  764. X * the software cursor is located.
  765. X */
  766. vteeol()
  767. {
  768. X    while (vtcol < term.t_ncol)
  769. X        vtputc(' ',FALSE);
  770. }
  771. X
  772. /* upscreen:    user routine to force a screen update
  773. X        always finishes complete update        */
  774. upscreen(f, n)
  775. {
  776. X    update(TRUE);
  777. X    return(TRUE);
  778. }
  779. X
  780. int scrflags;
  781. /*
  782. X * Make sure that the display is right. This is a three part process. First,
  783. X * scan through all of the windows looking for dirty ones. Check the framing,
  784. X * and refresh the screen. Second, make sure that "currow" and "curcol" are
  785. X * correct for the current window. Third, make the virtual and physical
  786. X * screens the same.
  787. X */
  788. update(force)
  789. int force;    /* force update past type ahead? */
  790. {
  791. X    register WINDOW *wp;
  792. X    int screencol;
  793. X
  794. #if    TYPEAH
  795. X    if (force == FALSE && typahead())
  796. X        return(SORTOFTRUE);
  797. #endif
  798. #if    VISMAC == 0
  799. X    if (force == FALSE && (kbdmode == PLAY || dotcmdmode == PLAY))
  800. X        return(TRUE);
  801. #endif
  802. X
  803. X    displaying = TRUE;
  804. X
  805. X    /* first, propagate mode line changes to all instances of
  806. X        a buffer displayed in more than one window */
  807. X    wp = wheadp;
  808. X    while (wp != NULL) {
  809. X        if (wp->w_flag & WFMODE) {
  810. X            if (wp->w_bufp->b_nwnd > 1) {
  811. X                /* make sure all previous windows have this */
  812. X                register WINDOW *owp;
  813. X                owp = wheadp;
  814. X                while (owp != NULL) {
  815. X                    if (owp->w_bufp == wp->w_bufp)
  816. X                        owp->w_flag |= WFMODE;
  817. X                    owp = owp->w_wndp;
  818. X                }
  819. X            }
  820. X        }
  821. X        wp = wp->w_wndp;
  822. X    }
  823. X
  824. X    /* update any windows that need refreshing */
  825. X    wp = wheadp;
  826. X    while (wp != NULL) {
  827. X        if (wp->w_flag) {
  828. X            /* if the window has changed, service it */
  829. X            reframe(wp);    /* check the framing */
  830. X            if (wp->w_flag & (WFKILLS|WFINS)) {
  831. X                scrflags |= (wp->w_flag & (WFINS|WFKILLS));
  832. X                wp->w_flag &= ~(WFKILLS|WFINS);
  833. X            }
  834. X            if ((wp->w_flag & ~(/* WFMOVE| */WFMODE)) == WFEDIT)
  835. X                updone(wp);    /* update EDITed line */
  836. X            else if (wp->w_flag & ~(WFMOVE))
  837. X                updall(wp);    /* update all lines */
  838. X            if (scrflags || (wp->w_flag & WFMODE))
  839. X                modeline(wp);    /* update modeline */
  840. X            wp->w_flag = 0;
  841. X            wp->w_force = 0;
  842. X        }
  843. X        /* on to the next window */
  844. X        wp = wp->w_wndp;
  845. X    }
  846. X
  847. X    /* recalc the current hardware cursor location */
  848. X    screencol = updpos();
  849. X
  850. #if    MEMMAP
  851. X    /* update the cursor and flush the buffers */
  852. X    movecursor(currow, screencol);
  853. #endif
  854. X
  855. X    /* check for lines to de-extend */
  856. X    upddex();
  857. X
  858. #if    NeWS
  859. X    newsupd(force) ;
  860. #else
  861. X    /* if screen is garbage, re-plot it */
  862. X    if (sgarbf)
  863. X        updgar();
  864. X
  865. X    /* update the virtual screen to the physical screen */
  866. X    updupd(force);
  867. #endif
  868. X
  869. X    /* update the cursor and flush the buffers */
  870. X    movecursor(currow, screencol);
  871. X    TTflush();
  872. X    displaying = FALSE;
  873. #if SIGWINCH
  874. X    while (chg_width || chg_height)
  875. X        newscreensize(chg_height,chg_width);
  876. #endif
  877. X    return(TRUE);
  878. }
  879. X
  880. /*    reframe:    check to see if the cursor is on in the window
  881. X            and re-frame it if needed or wanted        */
  882. reframe(wp)
  883. WINDOW *wp;
  884. {
  885. X    register LINE *lp;
  886. X    register int i;
  887. X
  888. X    /* if not a requested reframe, check for a needed one */
  889. X    if ((wp->w_flag & WFFORCE) == 0) {
  890. #if SCROLLCODE
  891. X        /* loop from one line above the window to one line after */
  892. X        lp = lback(wp->w_linep);
  893. X        for (i = -1; i <= wp->w_ntrows; i++)
  894. #else
  895. X        /* loop through the window */
  896. X        lp = wp->w_linep;
  897. X        for (i = 0; i < wp->w_ntrows; i++)
  898. #endif
  899. X        {
  900. X
  901. X            /* if the line is in the window, no reframe */
  902. X            if (lp == wp->w_dotp) {
  903. #if SCROLLCODE
  904. X                /* if not _quite_ in, we'll reframe gently */
  905. X                if ( i < 0 || i == wp->w_ntrows) {
  906. X                    /* if the terminal can't help, then
  907. X                        we're simply outside */
  908. X                    if (term.t_scroll == NULL)
  909. X                        i = wp->w_force;
  910. X                    break;
  911. X                }
  912. #endif
  913. X                return(TRUE);
  914. X            }
  915. X
  916. X            /* if we are at the end of the file, reframe */
  917. X            if (i >= 0 && lp == wp->w_bufp->b_linep)
  918. X                break;
  919. X
  920. X            /* on to the next line */
  921. X            lp = lforw(lp);
  922. X        }
  923. X    }
  924. X
  925. #if SCROLLCODE
  926. X    if (i == -1) {    /* we're just above the window */
  927. X        i = 1;    /* put dot at first line */
  928. X        scrflags |= WFINS;
  929. X    } else if (i == wp->w_ntrows) { /* we're just below the window */
  930. X        i = -1;    /* put dot at last line */
  931. X        scrflags |= WFKILLS;
  932. X    } else /* put dot where requested */
  933. #endif
  934. X        i = wp->w_force;  /* (is 0, unless reposition() was called) */
  935. X
  936. X    wp->w_flag |= WFMODE;
  937. X    
  938. X    /* w_force specifies which line of the window dot should end up on */
  939. X    /*     positive --> lines from the top                */
  940. X    /*     negative --> lines from the bottom            */
  941. X    /*     zero --> middle of window                */
  942. X    
  943. X    /* enforce some maximums */
  944. X    if (i > 0) {
  945. X        if (--i >= wp->w_ntrows)
  946. X            i = wp->w_ntrows - 1;
  947. X    } else if (i < 0) {    /* negative update???? */
  948. X        i += wp->w_ntrows;
  949. X        if (i < 0)
  950. X            i = 0;
  951. X    } else
  952. X        i = wp->w_ntrows / 2;
  953. X
  954. X    /* backup to new line at top of window */
  955. X    lp = wp->w_dotp;
  956. X    while (i != 0 && lback(lp) != wp->w_bufp->b_linep) {
  957. X        --i;
  958. X        lp = lback(lp);
  959. X    }
  960. X
  961. X    if (lp == wp->w_bufp->b_linep)
  962. X        lp = lback(lp);
  963. X        
  964. X    /* and reset the current line-at-top-of-window */
  965. X    wp->w_linep = lp;
  966. X    wp->w_flag |= WFHARD;
  967. X    wp->w_flag &= ~WFFORCE;
  968. X    return(TRUE);
  969. }
  970. X
  971. /*    updone:    update the current line    to the virtual screen        */
  972. X
  973. updone(wp)
  974. WINDOW *wp;    /* window to update current line in */
  975. {
  976. X    register LINE *lp;    /* line to update */
  977. X    register int sline;    /* physical screen line to update */
  978. X
  979. X    /* search down the line we want */
  980. X    lp = wp->w_linep;
  981. X    sline = wp->w_toprow;
  982. X    while (lp != wp->w_dotp) {
  983. X        ++sline;
  984. X        lp = lforw(lp);
  985. X    }
  986. X
  987. X    l_to_vline(wp,lp,sline);
  988. X    vteeol();
  989. }
  990. X
  991. /*    updall:    update all the lines in a window on the virtual screen */
  992. X
  993. updall(wp)
  994. WINDOW *wp;    /* window to update lines in */
  995. {
  996. X    register LINE *lp;    /* line to update */
  997. X    register int sline;    /* physical screen line to update */
  998. X
  999. X    /* search down the lines, updating them */
  1000. X    lp = wp->w_linep;
  1001. X    sline = wp->w_toprow;
  1002. X    while (sline < wp->w_toprow + wp->w_ntrows) {
  1003. X        l_to_vline(wp,lp,sline);
  1004. X        vteeol();
  1005. X        if (lp != wp->w_bufp->b_linep)
  1006. X            lp = lforw(lp);
  1007. X        ++sline;
  1008. X    }
  1009. X
  1010. }
  1011. X
  1012. /* line to virtual screen line */
  1013. l_to_vline(wp,lp,sline)
  1014. WINDOW *wp;    /* window to update lines in */
  1015. LINE *lp;
  1016. {
  1017. X    int i,c;
  1018. X
  1019. X    /* and update the virtual line */
  1020. X    vscreen[sline]->v_flag |= VFCHG;
  1021. X    vscreen[sline]->v_flag &= ~VFREQ;
  1022. X    if (wp->w_sideways)
  1023. X        taboff = wp->w_sideways;
  1024. X    if (lp != wp->w_bufp->b_linep) {
  1025. X        vtmove(sline, -wp->w_sideways);
  1026. X        i = 0;
  1027. X        while ( i < llength(lp) ) {
  1028. X            vtputc(lgetc(lp, i), wp->w_bufp->b_mode & MDLIST);
  1029. X            ++i;
  1030. X        }
  1031. X        vtputc('\n', wp->w_bufp->b_mode & MDLIST);
  1032. X        if (wp->w_sideways) {
  1033. X            vscreen[sline]->v_text[0] = '<';
  1034. X            if (vtcol < 1) vtcol = 1;
  1035. X        }
  1036. X    } else {
  1037. X        vtmove(sline, 0);
  1038. X        vtputc('~',FALSE);
  1039. X    }
  1040. X    taboff = 0;
  1041. #if    COLOR
  1042. X    vscreen[sline]->v_rfcolor = wp->w_fcolor;
  1043. X    vscreen[sline]->v_rbcolor = wp->w_bcolor;
  1044. #endif
  1045. }
  1046. X
  1047. /*    updpos:    update the position of the hardware cursor and handle extended
  1048. X        lines. This is the only update for simple moves.
  1049. X        returns the screen column for the cursor    */
  1050. updpos()
  1051. {
  1052. X    register LINE *lp;
  1053. X    register int c;
  1054. X    register int i;
  1055. X
  1056. X    /* find the current row */
  1057. X    lp = curwp->w_linep;
  1058. X    currow = curwp->w_toprow;
  1059. X    while (lp != curwp->w_dotp) {
  1060. X        ++currow;
  1061. X        lp = lforw(lp);
  1062. X        if (lp == curwp->w_linep) {
  1063. X            mlwrite("Bug:  lost dot updpos().  setting at top");
  1064. X            curwp->w_linep = curwp->w_dotp  = lforw(curbp->b_linep);
  1065. X            currow = curwp->w_toprow;
  1066. X        }
  1067. X    }
  1068. X
  1069. X    /* find the current column */
  1070. X    curcol = -curwp->w_sideways;
  1071. X    i = 0;
  1072. X    while (i < curwp->w_doto) {
  1073. X        c = lgetc(lp, i++);
  1074. X        if (((curwp->w_bufp->b_mode&MDLIST) == 0) && c == '\t') {
  1075. X            do {
  1076. X                curcol++;
  1077. X            } while (((curcol + curwp->w_sideways)&TABMASK) != 0);
  1078. X        } else {
  1079. X            if (!isprint(c))
  1080. X                ++curcol;
  1081. X            ++curcol;
  1082. X        }
  1083. X
  1084. X    }
  1085. X
  1086. X    /* if extended, flag so and update the virtual line image */
  1087. X    if (curcol >=  term.t_ncol - 1) {
  1088. X        return updext_past();
  1089. X    } else if (curwp->w_sideways && curcol < 1){
  1090. X        return updext_before();
  1091. X    } else {
  1092. X        return curcol;
  1093. X    }
  1094. }
  1095. X
  1096. /*    upddex:    de-extend any line that deserves it        */
  1097. X
  1098. upddex()
  1099. {
  1100. X    register WINDOW *wp;
  1101. X    register LINE *lp;
  1102. X    register int i,j;
  1103. X
  1104. X    wp = wheadp;
  1105. X
  1106. X    while (wp != NULL) {
  1107. X        lp = wp->w_linep;
  1108. X        i = wp->w_toprow;
  1109. X
  1110. X        while (i < wp->w_toprow + wp->w_ntrows) {
  1111. X            if (vscreen[i]->v_flag & VFEXT) {
  1112. X                if ((wp != curwp) || (lp != wp->w_dotp) ||
  1113. X                   (curcol < term.t_ncol - 1)) {
  1114. X                    l_to_vline(wp,lp,i);
  1115. X                    vteeol();
  1116. X                    /* this line no longer is extended */
  1117. X                    vscreen[i]->v_flag &= ~VFEXT;
  1118. X                }
  1119. X            }
  1120. X            lp = lforw(lp);
  1121. X            ++i;
  1122. X        }
  1123. X        /* and onward to the next window */
  1124. X        wp = wp->w_wndp;
  1125. X    }
  1126. }
  1127. X
  1128. /*    updgar:    if the screen is garbage, clear the physical screen and
  1129. X        the virtual screen and force a full update        */
  1130. X
  1131. updgar()
  1132. {
  1133. X    register char *txt;
  1134. X    register int i,j;
  1135. X
  1136. X    for (i = 0; i < term.t_nrow; ++i) {
  1137. X        vscreen[i]->v_flag |= VFCHG;
  1138. #if    REVSTA
  1139. X        vscreen[i]->v_flag &= ~VFREV;
  1140. #endif
  1141. #if    COLOR
  1142. X        vscreen[i]->v_fcolor = gfcolor;
  1143. X        vscreen[i]->v_bcolor = gbcolor;
  1144. #endif
  1145. #if    ! MEMMAP
  1146. X        txt = pscreen[i]->v_text;
  1147. X        for (j = 0; j < term.t_ncol; ++j)
  1148. X            txt[j] = ' ';
  1149. #endif
  1150. X    }
  1151. X
  1152. X    movecursor(0, 0);         /* Erase the screen. */
  1153. X    (*term.t_eeop)();
  1154. X    sgarbf = FALSE;             /* Erase-page clears */
  1155. X    mpresf = FALSE;             /* the message area. */
  1156. #if    COLOR
  1157. X    mlerase();            /* needs to be cleared if colored */
  1158. #endif
  1159. }
  1160. X
  1161. /*    updupd:    update the physical screen from the virtual screen    */
  1162. X
  1163. updupd(force)
  1164. int force;    /* forced update flag */
  1165. {
  1166. X    register VIDEO *vp1;
  1167. X    register int i;
  1168. #if SCROLLCODE
  1169. X    if (scrflags & WFKILLS)
  1170. X        scrolls(FALSE);
  1171. X    if (scrflags & WFINS)
  1172. X        scrolls(TRUE);
  1173. X    scrflags = 0;
  1174. #endif
  1175. X
  1176. X    for (i = 0; i < term.t_nrow; ++i) {
  1177. X        vp1 = vscreen[i];
  1178. X
  1179. X        /* for each line that needs to be updated*/
  1180. X        if ((vp1->v_flag & VFCHG) != 0) {
  1181. #if    TYPEAH
  1182. X            if (force == FALSE && typahead())
  1183. X                return(TRUE);
  1184. #endif
  1185. #if    MEMMAP
  1186. X            updateline(i, vp1);
  1187. #else
  1188. X            updateline(i, vp1, pscreen[i]);
  1189. #endif
  1190. X        }
  1191. X    }
  1192. X    return(TRUE);
  1193. }
  1194. X
  1195. #if SCROLLCODE
  1196. /* optimize out scrolls (line breaks, and newlines) */
  1197. /* arg. chooses between looking for inserts or deletes */
  1198. int    
  1199. scrolls(inserts)    /* returns true if it does something */
  1200. {
  1201. X    struct    VIDEO *vpv ;    /* virtual screen image */
  1202. X    struct    VIDEO *vpp ;    /* physical screen image */
  1203. X    int    i, j, k ;
  1204. X    int    rows, cols ;
  1205. X    int    first, match, count, ptarget, vtarget, end ;
  1206. X    int    longmatch, longcount;
  1207. X    int    from, to;
  1208. X
  1209. X    if (!term.t_scroll) /* no way to scroll */
  1210. X        return FALSE;
  1211. X
  1212. X    rows = term.t_nrow ;
  1213. X    cols = term.t_ncol ;
  1214. X
  1215. X    first = -1 ;
  1216. X    for (i = 0; i < rows; i++) {    /* find first wrong line */
  1217. X        if (!texttest(i,i)) {
  1218. X            first = i;
  1219. X            break;
  1220. X        }
  1221. X    }
  1222. X
  1223. X    if (first < 0)
  1224. X        return FALSE;        /* no text changes */
  1225. X
  1226. X    vpv = vscreen[first] ;
  1227. X    vpp = pscreen[first] ;
  1228. X
  1229. X    if (inserts) {
  1230. X        /* determine types of potential scrolls */
  1231. X        end = endofline(vpv->v_text,cols) ;
  1232. X        if ( end == 0 )
  1233. X            ptarget = first ;        /* newlines */
  1234. X        else if ( strncmp(vpp->v_text, vpv->v_text, end) == 0 )
  1235. X            ptarget = first + 1 ;    /* broken line newlines */
  1236. X        else 
  1237. X            ptarget = first ;
  1238. X    } else {
  1239. X        vtarget = first + 1 ;
  1240. X    }
  1241. X
  1242. X    /* find the matching shifted area */
  1243. X    match = -1 ;
  1244. X    longmatch = -1;
  1245. X    longcount = 0;
  1246. X    from = inserts ? ptarget : vtarget;
  1247. X    for (i = from+1; i < rows; i++) {
  1248. X        if (inserts ? texttest(i,from) : texttest(from,i) ) {
  1249. X            match = i ;
  1250. X            count = 1 ;
  1251. X            for (j=match+1, k=from+1; j<rows && k<rows; j++, k++) {
  1252. X                if (inserts ? texttest(j,k) : texttest(k,j))
  1253. X                    count++ ;
  1254. X                else
  1255. X                    break ;
  1256. X            }
  1257. X            if (longcount < count) {
  1258. X                longcount = count;
  1259. X                longmatch = match;
  1260. X            }
  1261. X        }
  1262. X    }
  1263. X    match = longmatch;
  1264. X    count = longcount;
  1265. X
  1266. X    if (!inserts) {
  1267. X        /* full kill case? */
  1268. X        if (match > 0 && texttest(first, match-1)) {
  1269. X            vtarget-- ;
  1270. X            match-- ;
  1271. X            count++ ;
  1272. X        }
  1273. X    }
  1274. X
  1275. X    /* do the scroll */
  1276. X    if (match>0 && count>2) {         /* got a scroll */
  1277. X        /* move the count lines starting at ptarget to match */
  1278. X        /* mlwrite("scrolls: move the %d lines starting at %d to %d",
  1279. X                        count,ptarget,match);
  1280. X        */
  1281. X        if (inserts) {
  1282. X            from = ptarget;
  1283. X            to = match;
  1284. X        } else {
  1285. X            from = match;
  1286. X            to = vtarget;
  1287. X        }
  1288. X        scrscroll(from, to, count) ;
  1289. X        for (i = 0; i < count; i++) {
  1290. X            vpp = pscreen[to+i] ;
  1291. X            vpv = vscreen[to+i];
  1292. X            strncpy(vpp->v_text, vpv->v_text, cols) ;
  1293. X        }
  1294. X        if (inserts) {
  1295. X            from = ptarget;
  1296. X            to = match;
  1297. X        } else {
  1298. X            from = vtarget+count;
  1299. X            to = match+count;
  1300. X        }
  1301. X        for (i = from; i < to; i++) {
  1302. X            char *txt;
  1303. X            txt = pscreen[i]->v_text;
  1304. X            for (j = 0; j < term.t_ncol; ++j)
  1305. X                txt[j] = ' ';
  1306. X            vscreen[i]->v_flag |= VFCHG;
  1307. X        }
  1308. X        return(TRUE) ;
  1309. X    }
  1310. X    return(FALSE) ;
  1311. }
  1312. X
  1313. /* move the "count" lines starting at "from" to "to" */
  1314. scrscroll(from, to, count)
  1315. {
  1316. X    ttrow = ttcol = -1;
  1317. X    (*term.t_scroll)(from,to,count);
  1318. }
  1319. X
  1320. texttest(vrow,prow)        /* return TRUE on text match */
  1321. int    vrow, prow ;        /* virtual, physical rows */
  1322. {
  1323. struct    VIDEO *vpv = vscreen[vrow] ;    /* virtual screen image */
  1324. struct    VIDEO *vpp = pscreen[prow]  ;    /* physical screen image */
  1325. X
  1326. X    return (!memcmp(vpv->v_text, vpp->v_text, term.t_ncol)) ;
  1327. }
  1328. X
  1329. /* return the index of the first blank of trailing whitespace */
  1330. int    
  1331. endofline(s,n) 
  1332. char     *s ;
  1333. {
  1334. int    i ;
  1335. X    for (i = n - 1; i >= 0; i--)
  1336. X        if (s[i] != ' ') return(i+1) ;
  1337. X    return(0) ;
  1338. }
  1339. X
  1340. #endif /* SCROLLCODE */
  1341. X
  1342. X
  1343. /*    updext_past: update the extended line which the cursor is currently
  1344. X        on at a column greater than the terminal width. The line
  1345. X        will be scrolled right or left to let the user see where
  1346. X        the cursor is        */
  1347. updext_past()
  1348. {
  1349. X    register int lbound, rcursor;
  1350. X    register LINE *lp;    /* pointer to current line */
  1351. X    register int j;        /* index into line */
  1352. X
  1353. X    /* calculate what column the real cursor will end up in */
  1354. X    /* why is term.t_ncol in here? */
  1355. X    rcursor = ((curcol - term.t_ncol) % term.t_scrsiz) + term.t_margin;
  1356. X    lbound = curcol - rcursor;
  1357. X    taboff = lbound + curwp->w_sideways;
  1358. X
  1359. X    /* scan through the line outputing characters to the virtual screen */
  1360. X    /* once we reach the left edge                    */
  1361. X    vtmove(currow, -lbound-curwp->w_sideways);    /* start scanning offscreen */
  1362. X    lp = curwp->w_dotp;        /* line to output */
  1363. X    for (j = 0; j < llength(lp); ++j)
  1364. X        vtputc(lgetc(lp, j), curwp->w_bufp->b_mode&MDLIST);
  1365. X    vtputc('\n', curwp->w_bufp->b_mode&MDLIST);
  1366. X
  1367. X    /* truncate the virtual line, restore tab offset */
  1368. X    vteeol();
  1369. X    taboff = 0;
  1370. X
  1371. X    /* and put a '<' in column 1 */
  1372. X    vscreen[currow]->v_text[0] = '<';
  1373. X    vscreen[currow]->v_flag |= (VFEXT | VFCHG);
  1374. X    return rcursor;
  1375. }
  1376. X
  1377. /*    updext_before: update the extended line which the cursor is currently
  1378. X        on at a column less than the terminal width. The line
  1379. X        will be scrolled right or left to let the user see where
  1380. X        the cursor is        */
  1381. updext_before()
  1382. {
  1383. X    register int lbound, rcursor;
  1384. X    register LINE *lp;    /* pointer to current line */
  1385. X    register int j;        /* index into line */
  1386. X
  1387. X    /* calculate what column the real cursor will end up in */
  1388. X    rcursor = (curcol % (term.t_ncol-term.t_margin));
  1389. X    lbound = curcol - rcursor + 1;
  1390. X    taboff = lbound;
  1391. X
  1392. X    /* scan through the line outputing characters to the virtual screen */
  1393. X    /* once we reach the left edge                    */
  1394. X    vtmove(currow, -lbound);    /* start scanning offscreen */
  1395. X    lp = curwp->w_dotp;        /* line to output */
  1396. X    for (j = 0; j < llength(lp); ++j)
  1397. X        vtputc(lgetc(lp, j), curwp->w_bufp->b_mode&MDLIST);
  1398. X    vtputc('\n', curwp->w_bufp->b_mode&MDLIST);
  1399. X
  1400. X    /* truncate the virtual line, restore tab offset */
  1401. X    vteeol();
  1402. X    taboff = 0;
  1403. X
  1404. X    /* and put a '<' in column 1 */
  1405. X    vscreen[currow]->v_text[0] = '<';
  1406. X    vscreen[currow]->v_flag |= (VFEXT | VFCHG);
  1407. X    return rcursor;
  1408. }
  1409. X
  1410. X
  1411. #if    NeWS
  1412. newsupd(force)    /* update the physical screen from the virtual screen */
  1413. int force;    /* forced update flag */
  1414. {
  1415. register int i ;
  1416. struct    VIDEO *vpv ;    /* virtual screen image */
  1417. struct    VIDEO *vpp ;    /* physical screen image */
  1418. int    bad, badcol, rows ;
  1419. X
  1420. X    rows = term.t_nrow ;
  1421. X
  1422. X    if (force == FALSE && typahead()) return ;
  1423. X    if (sgarbf) {
  1424. X        fastupdate() ;
  1425. X        return ;
  1426. X    }
  1427. X
  1428. X    /* if enough lines are bad try to optimize scrolls/kills */    
  1429. X    for (bad = 0, i = 0; i < rows; ++i)
  1430. X        if (!texttest(i,i)) {
  1431. X            bad++ ;
  1432. X            if (bad > 3) {
  1433. X                if (!scrolls()) kills() ;
  1434. X                break ;
  1435. X            }
  1436. X        }
  1437. X
  1438. X    /* count bad lines, if enough need fixed redo whole screen */
  1439. X    for (bad = 0, badcol = 0, i = 0; i < rows; ++i) {
  1440. X        vpv = vscreen[i] ;
  1441. X        vpv->v_flag &= ~(VFCHG|VFCOL) ;        /* clear flag */
  1442. X        if (!texttest(i,i)) {
  1443. X            vpv->v_flag |= VFCHG ;
  1444. X            bad++ ;
  1445. X        }
  1446. X        if (!colortest(i)) {
  1447. X            vpv->v_flag |= VFCOL ;
  1448. X            badcol++  ;
  1449. X        }
  1450. X    }
  1451. X    if (bad == 0 && badcol > 0) {    /* pure color update */
  1452. X        colorupdate() ;
  1453. X        return ;
  1454. X    }
  1455. X    if (bad > (3*rows)/4) {        /* full update */
  1456. X        fastupdate() ;
  1457. X        return ;
  1458. X    }
  1459. X
  1460. X    /* Fix the bad lines one by one */
  1461. X    for (i = 0; i < rows; ++i)
  1462. X        if (vscreen[i]->v_flag & (VFCHG|VFCOL)) updateline(i) ;
  1463. }
  1464. X
  1465. X
  1466. /* optimize out scrolls (line breaks, and newlines) */
  1467. int    scrolls()    /* returns true if it does something */
  1468. {
  1469. struct    VIDEO *vpv ;    /* virtual screen image */
  1470. struct    VIDEO *vpp ;    /* physical screen image */
  1471. int    i, j, k ;
  1472. int    rows, cols ;
  1473. int    first, match, count, ptarget, end ;
  1474. X
  1475. X    rows = term.t_nrow ;
  1476. X    cols = term.t_ncol ;
  1477. X
  1478. X    first = -1 ;
  1479. X    for (i = 0; i < rows; i++)    /* find first wrong line */
  1480. X        if (!texttest(i,i)) {first = i ; break ;}
  1481. X
  1482. X    if (first < 0) return(FALSE) ;        /* no text changes */
  1483. X
  1484. X    vpv = vscreen[first] ;
  1485. X    vpp = pscreen[first] ;
  1486. X
  1487. X    /* determine types of potential scrolls */
  1488. X    end = endofline(vpv->v_text,cols) ;
  1489. X    if ( end == 0 )
  1490. X        ptarget = first ;        /* newlines */
  1491. X    else if ( strncmp(vpp->v_text, vpv->v_text, end) == 0 )
  1492. X        ptarget = first + 1 ;    /* broken line newlines */
  1493. X    else return(FALSE) ;            /* no scrolls */
  1494. X
  1495. X    /* find the matching shifted area */
  1496. X    match = -1 ;
  1497. X    for (i = ptarget+1; i < rows; i++) {
  1498. X        if (texttest(i, ptarget)) {
  1499. X            match = i ;
  1500. X            count = 1 ;
  1501. X            for (j=match+1, k=ptarget+1; j<rows && k<rows; j++, k++) {
  1502. X                if (texttest(j,k))
  1503. X                    count++ ;
  1504. X                else
  1505. X                    break ;
  1506. X            }
  1507. X            break ;
  1508. X        }
  1509. X    }
  1510. X
  1511. X    /* do the scroll */
  1512. X    if (match>0 && count>2) {         /* got a scroll */
  1513. X        newsscroll(ptarget, match, count) ;
  1514. X        for (i = 0; i < count; i++) {
  1515. X            vpv = vscreen[match+i] ; vpp = pscreen[match+i] ;
  1516. X            strncpy(vpp->v_text, vpv->v_text, cols) ;
  1517. X        }
  1518. X        return(TRUE) ;
  1519. X    }
  1520. X    return(FALSE) ;
  1521. }
  1522. X
  1523. X
  1524. /* optimize out line kills (full and with a partial kill) */
  1525. int    kills()        /* returns true if it does something */
  1526. {
  1527. struct    VIDEO *vpv ;    /* virtual screen image */
  1528. struct    VIDEO *vpp ;    /* physical screen image */
  1529. int    i, j, k ;
  1530. int    rows, cols ;
  1531. int    first, match, count, vtarget, end ;
  1532. X
  1533. X    rows = term.t_nrow ;
  1534. X    cols = term.t_ncol ;
  1535. X
  1536. X    first = -1 ;
  1537. X    for (i = 0; i < rows; i++)    /* find first wrong line */
  1538. X        if (!texttest(i,i)) {first = i ; break ;}
  1539. X
  1540. X    if (first < 0) return(FALSE) ;        /* no text changes */
  1541. X
  1542. X    vpv = vscreen[first] ;
  1543. X    vpp = pscreen[first] ;
  1544. X
  1545. X    vtarget = first + 1 ;
  1546. X
  1547. X    /* find the matching shifted area */
  1548. X    match = -1 ;
  1549. X    for (i = vtarget+1; i < rows; i++) {
  1550. X        if (texttest(vtarget, i)) {
  1551. X            match = i ;
  1552. X            count = 1 ;
  1553. X            for (j=match+1, k=vtarget+1; j<rows && k<rows; j++, k++) {
  1554. X                if (texttest(k,j))
  1555. X                    count++ ;
  1556. X                else
  1557. X                    break ;
  1558. X            }
  1559. X            break ;
  1560. X        }
  1561. X    }
  1562. X    if (texttest(first, match-1)) {        /* full kill case */
  1563. X        vtarget-- ;
  1564. X        match-- ;
  1565. X        count++ ;
  1566. X    }
  1567. X
  1568. X    /* do the scroll */
  1569. X    if (match>0 && count>2) {        /* got a scroll */
  1570. X        newsscroll(match, vtarget, count) ;
  1571. X        for (i = 0; i < count; i++) {
  1572. X            vpv = vscreen[vtarget+i] ; vpp = pscreen[vtarget+i] ;
  1573. X            strncpy(vpp->v_text, vpv->v_text, cols) ;
  1574. X        }
  1575. X        return(TRUE) ;
  1576. X    }
  1577. X    return(FALSE) ;
  1578. }
  1579. X
  1580. X
  1581. texttest(vrow,prow)        /* return TRUE on text match */
  1582. int    vrow, prow ;        /* virtual, physical rows */
  1583. {
  1584. struct    VIDEO *vpv = vscreen[vrow] ;    /* virtual screen image */
  1585. struct    VIDEO *vpp = pscreen[prow]  ;    /* physical screen image */
  1586. X
  1587. X    vpp->v_text[term.t_ncol] = 0 ;
  1588. X    vpv->v_text[term.t_ncol] = 0 ;
  1589. X    return (!strncmp(vpv->v_text, vpp->v_text, term.t_ncol)) ;
  1590. }
  1591. X
  1592. colortest(row)            /* TRUE on color match */
  1593. int    row ;    
  1594. {
  1595. struct    VIDEO *vpv = vscreen[row] ;    /* virtual screen image */
  1596. X
  1597. X    return (vpv->v_fcolor == vpv->v_rfcolor &&
  1598. X        vpv->v_bcolor == vpv->v_rbcolor) ;
  1599. }
  1600. X
  1601. X
  1602. updateline(row)
  1603. int    row ;        /* row of screen to update */
  1604. {
  1605. struct    VIDEO *vpv = vscreen[row] ;    /* virtual screen image */
  1606. struct    VIDEO *vpp = pscreen[row]  ;    /* physical screen image */
  1607. int    end ;
  1608. X
  1609. X    end = endofline(vpv->v_text, term.t_ncol) ;
  1610. X    strncpy(vpp->v_text, vpv->v_text, term.t_ncol) ;
  1611. X    vpv->v_text[end] = 0 ;
  1612. X    newsputline(row, vpv->v_text, vpv->v_rfcolor, vpv->v_rbcolor) ;
  1613. X    vpv->v_text[end] = ' ' ;
  1614. X    vpv->v_fcolor = vpv->v_rfcolor;
  1615. X    vpv->v_bcolor = vpv->v_rbcolor;
  1616. X    vpv->v_flag &= ~(VFCHG|VFCOL);    /* clear flag */
  1617. }
  1618. X
  1619. X
  1620. colorupdate()
  1621. {
  1622. struct    VIDEO *vpv ;    /* virtual screen image */
  1623. int    row ;
  1624. X    
  1625. X    for (row=0; row<term.t_nrow; row++) {    /* send the row colors */
  1626. X        vpv = vscreen[row] ;
  1627. X        if (vpv->v_flag & VFCOL) {
  1628. X            newssetrowcolors(row, vpv->v_rfcolor, vpv->v_rbcolor) ;
  1629. X            vpv->v_fcolor = vpv->v_rfcolor;
  1630. X            vpv->v_bcolor = vpv->v_rbcolor;
  1631. X        }
  1632. X        vpv->v_flag &= ~VFCOL ;
  1633. X    }
  1634. X
  1635. X    newslocalupdate() ;    /* ask for a screen refresh */
  1636. }
  1637. X
  1638. X
  1639. fastupdate()        /* redo the entire screen fast */
  1640. {
  1641. int    row ;
  1642. register char    *cp, *first ;
  1643. struct    VIDEO *vpv ;    /* virtual screen image */
  1644. struct    VIDEO *vpp ;    /* physical screen image */
  1645. X
  1646. X    /* send the row colors */
  1647. X    for (row=0; row<term.t_nrow; row++) {
  1648. X        vpv = vscreen[row] ;
  1649. X        if (!colortest(row)) {
  1650. X            newssetrowcolors(row, vpv->v_rfcolor, vpv->v_rbcolor) ;
  1651. X            vpv->v_fcolor = vpv->v_rfcolor;
  1652. X            vpv->v_bcolor = vpv->v_rbcolor;
  1653. X        }
  1654. X        vpv->v_flag &= ~VFCOL ;
  1655. X    }
  1656. X
  1657. X    /* virtual -> physical buffer */
  1658. X    for (row=0; row<term.t_nrow; row++) {
  1659. X        vpv = vscreen[row] ; vpp = pscreen[row] ;
  1660. X        memcpy(vpp->v_text, vpv->v_text, term.t_ncol);
  1661. X        vpp->v_text[term.t_ncol] = 0 ;
  1662. X        vpv->v_text[term.t_ncol] = 0 ;
  1663. X        vpv->v_flag &= ~VFCHG;
  1664. X    }
  1665. X    /* send the stuff */
  1666. X    newscls() ;
  1667. X    for (row=0; row<term.t_nrow; row++) {
  1668. X        first = pscreen[row]->v_text ;
  1669. X        /* don't send trailing blanks */
  1670. X        cp = &first[endofline(first,term.t_ncol)] ;
  1671. X        if (cp > first) {
  1672. X            *cp = 0 ;
  1673. X            newsfastputline(row, first) ;
  1674. X            *cp = ' ' ;
  1675. X        }
  1676. X    }
  1677. X    sgarbf = FALSE;
  1678. }
  1679. X
  1680. /* return the index of the first blank of trailing whitespace */
  1681. int    endofline(s,n) 
  1682. char     *s ;
  1683. {
  1684. int    i ;
  1685. X    for (i = n - 1; i >= 0; i--)
  1686. X        if (s[i] != ' ') return(i+1) ;
  1687. X    return(0) ;
  1688. }
  1689. #else
  1690. X
  1691. /*
  1692. X * Update a single line. This does not know how to use insert or delete
  1693. X * character sequences; we are using VT52 functionality. Update the physical
  1694. X * row and column variables. It does try an exploit erase to end of line. The
  1695. X * RAINBOW version of this routine uses fast video.
  1696. X */
  1697. #if    MEMMAP
  1698. /*    UPDATELINE specific code for the IBM-PC and other compatables */
  1699. X
  1700. updateline(row, vp1)
  1701. X
  1702. int row;        /* row of screen to update */
  1703. struct VIDEO *vp1;    /* virtual screen image */
  1704. X
  1705. {
  1706. #if    COLOR
  1707. X    scwrite(row, vp1->v_text, vp1->v_rfcolor, vp1->v_rbcolor);
  1708. X    vp1->v_fcolor = vp1->v_rfcolor;
  1709. X    vp1->v_bcolor = vp1->v_rbcolor;
  1710. #else
  1711. X    if (vp1->v_flag & VFREQ)
  1712. X        scwrite(row, vp1->v_text, 0, 7);
  1713. X    else
  1714. X        scwrite(row, vp1->v_text, 7, 0);
  1715. #endif
  1716. X    vp1->v_flag &= ~(VFCHG | VFCOL);    /* flag this line as changed */
  1717. X
  1718. }
  1719. X
  1720. #else
  1721. X
  1722. updateline(row, vp1, vp2)
  1723. X
  1724. int row;        /* row of screen to update */
  1725. struct VIDEO *vp1;    /* virtual screen image */
  1726. struct VIDEO *vp2;    /* physical screen image */
  1727. X
  1728. {
  1729. #if RAINBOW
  1730. /*    UPDATELINE specific code for the DEC rainbow 100 micro    */
  1731. X
  1732. X    register char *cp1;
  1733. X    register char *cp2;
  1734. X    register int nch;
  1735. X
  1736. X    /* since we don't know how to make the rainbow do this, turn it off */
  1737. X    flags &= (~VFREV & ~VFREQ);
  1738. X
  1739. X    cp1 = &vp1->v_text[0];                    /* Use fast video. */
  1740. X    cp2 = &vp2->v_text[0];
  1741. X    putline(row+1, 1, cp1);
  1742. X    nch = term.t_ncol;
  1743. X
  1744. X    do
  1745. X        {
  1746. X        *cp2 = *cp1;
  1747. X        ++cp2;
  1748. X        ++cp1;
  1749. X        }
  1750. X    while (--nch);
  1751. X    *flags &= ~VFCHG;
  1752. #else
  1753. /*    UPDATELINE code for all other versions        */
  1754. X
  1755. X    register char *cp1;
  1756. X    register char *cp2;
  1757. X    register char *cp3;
  1758. X    register char *cp4;
  1759. X    register char *cp5;
  1760. X    register int nbflag;    /* non-blanks to the right flag? */
  1761. X    int rev;        /* reverse video flag */
  1762. X    int req;        /* reverse video request flag */
  1763. X
  1764. X
  1765. X    /* set up pointers to virtual and physical lines */
  1766. X    cp1 = &vp1->v_text[0];
  1767. X    cp2 = &vp2->v_text[0];
  1768. X
  1769. #if    COLOR
  1770. X    TTforg(vp1->v_rfcolor);
  1771. X    TTbacg(vp1->v_rbcolor);
  1772. #endif
  1773. X
  1774. #if    REVSTA | COLOR
  1775. X    /* if we need to change the reverse video status of the
  1776. X       current line, we need to re-write the entire line     */
  1777. X    rev = (vp1->v_flag & VFREV) == VFREV;
  1778. X    req = (vp1->v_flag & VFREQ) == VFREQ;
  1779. X    if ((rev != req)
  1780. #if    COLOR
  1781. X        || (vp1->v_fcolor != vp1->v_rfcolor) || (vp1->v_bcolor != vp1->v_rbcolor)
  1782. #endif
  1783. #if    HP150
  1784. X    /* the HP150 has some reverse video problems */
  1785. X        || req || rev
  1786. #endif
  1787. X            ) {
  1788. X        movecursor(row, 0);    /* Go to start of line. */
  1789. X        /* set rev video if needed */
  1790. X        if (rev != req)
  1791. X            (*term.t_rev)(req);
  1792. X
  1793. X        /* scan through the line and dump it to the screen and
  1794. X           the virtual screen array                */
  1795. X        cp3 = &vp1->v_text[term.t_ncol];
  1796. X        while (cp1 < cp3) {
  1797. X            TTputc(*cp1);
  1798. X            ++ttcol;
  1799. X            *cp2++ = *cp1++;
  1800. X        }
  1801. X        /* turn rev video off */
  1802. X        if (rev != req)
  1803. X            (*term.t_rev)(FALSE);
  1804. X
  1805. X        /* update the needed flags */
  1806. X        vp1->v_flag &= ~VFCHG;
  1807. X        if (req)
  1808. X            vp1->v_flag |= VFREV;
  1809. X        else
  1810. X            vp1->v_flag &= ~VFREV;
  1811. #if    COLOR
  1812. X        vp1->v_fcolor = vp1->v_rfcolor;
  1813. X        vp1->v_bcolor = vp1->v_rbcolor;
  1814. #endif
  1815. X        return(TRUE);
  1816. X    }
  1817. #endif
  1818. X
  1819. X    /* advance past any common chars at the left */
  1820. X    while (cp1 != &vp1->v_text[term.t_ncol] && *cp1 == *cp2) {
  1821. X        ++cp1;
  1822. X        ++cp2;
  1823. X    }
  1824. X
  1825. /* This can still happen, even though we only call this routine on changed
  1826. X * lines. A hard update is always done when a line splits, a massive
  1827. X * change is done, or a buffer is displayed twice. This optimizes out most
  1828. X * of the excess updating. A lot of computes are used, but these tend to
  1829. X * be hard operations that do a lot of update, so I don't really care.
  1830. X */
  1831. X    /* if both lines are the same, no update needs to be done */
  1832. X    if (cp1 == &vp1->v_text[term.t_ncol]) {
  1833. X         vp1->v_flag &= ~VFCHG;        /* flag this line is changed */
  1834. X        return(TRUE);
  1835. X    }
  1836. X
  1837. X    /* find out if there is a match on the right */
  1838. X    nbflag = FALSE;
  1839. X    cp3 = &vp1->v_text[term.t_ncol];
  1840. X    cp4 = &vp2->v_text[term.t_ncol];
  1841. X
  1842. X    while (cp3[-1] == cp4[-1]) {
  1843. X        --cp3;
  1844. X        --cp4;
  1845. X        if (cp3[0] != ' ')        /* Note if any nonblank */
  1846. X            nbflag = TRUE;        /* in right match. */
  1847. X    }
  1848. X
  1849. X    cp5 = cp3;
  1850. X
  1851. X    /* Erase to EOL ? */
  1852. X    if (nbflag == FALSE && eolexist == TRUE && (req != TRUE)) {
  1853. X        while (cp5!=cp1 && cp5[-1]==' ')
  1854. X            --cp5;
  1855. X
  1856. X        if (cp3-cp5 <= 3)        /* Use only if erase is */
  1857. X            cp5 = cp3;        /* fewer characters. */
  1858. X    }
  1859. X
  1860. X    movecursor(row, cp1 - &vp1->v_text[0]);    /* Go to start of line. */
  1861. #if    REVSTA
  1862. X    TTrev(rev);
  1863. #endif
  1864. X
  1865. X    while (cp1 != cp5) {        /* Ordinary. */
  1866. X        TTputc(*cp1);
  1867. X        ++ttcol;
  1868. X        *cp2++ = *cp1++;
  1869. X    }
  1870. X
  1871. X    if (cp5 != cp3) {        /* Erase. */
  1872. X        TTeeol();
  1873. X        while (cp1 != cp3)
  1874. X            *cp2++ = *cp1++;
  1875. X    }
  1876. #if    REVSTA
  1877. X    TTrev(FALSE);
  1878. #endif
  1879. X    vp1->v_flag &= ~VFCHG;        /* flag this line as updated */
  1880. X    return(TRUE);
  1881. #endif
  1882. }
  1883. #endif
  1884. X
  1885. #endif  /* NeWS */
  1886. X
  1887. /*
  1888. X * Redisplay the mode line for the window pointed to by the "wp". This is the
  1889. X * only routine that has any idea of how the modeline is formatted. You can
  1890. X * change the modeline format by hacking at this routine. Called by "update"
  1891. X * any time there is a dirty window.
  1892. X */
  1893. modeline(wp)
  1894. WINDOW *wp;
  1895. {
  1896. X    register int n;
  1897. X    register BUFFER *bp;
  1898. X    register lchar;        /* character to draw line in buffer with */
  1899. X
  1900. X    n = wp->w_toprow+wp->w_ntrows;          /* Location. */
  1901. X    vscreen[n]->v_flag |= VFCHG | VFREQ | VFCOL;/* Redraw next time. */
  1902. X
  1903. #if    NeWS
  1904. X    vscreen[n]->v_rfcolor = 0;
  1905. X    vscreen[n]->v_rbcolor = 7;
  1906. X    if (wp == curwp) {            /* mark the current buffer */
  1907. X        lchar = '^' ;
  1908. X    } else {
  1909. X        lchar = ' ' ;
  1910. X    }
  1911. X    vtmove(n, 0);                          /* Seek to right line. */
  1912. #else
  1913. X
  1914. #if    COLOR
  1915. X    vscreen[n]->v_rfcolor = 0;            /* black on */
  1916. X    vscreen[n]->v_rbcolor = 7;            /* white.....*/
  1917. #endif
  1918. X    vtmove(n, 0);                           /* Seek to right line. */
  1919. X    if (wp == curwp) {                /* mark the current buffer */
  1920. X        lchar = '=';
  1921. X    } else {
  1922. #if    REVSTA
  1923. X        if (revexist)
  1924. X            lchar = ' ';
  1925. X        else
  1926. #endif
  1927. X            lchar = '-';
  1928. #endif
  1929. X    }
  1930. X    bp = wp->w_bufp;
  1931. X
  1932. X    vtputc(lchar,FALSE);
  1933. X    vtputc(' ',FALSE);
  1934. X    vtputsn(bp->b_bname, NBUFN);
  1935. X    if (bp->b_mode&MDVIEW)
  1936. X        vtputsn(" [view only]", 20);
  1937. X    if (bp->b_mode&MDDOS)
  1938. X        vtputsn(" [dos-style]", 20);
  1939. X    if (bp->b_flag&BFCHG)
  1940. X        vtputsn(" [modified]", 20);
  1941. X    /* don't print a filename if they're the same, 
  1942. X        or the filename is null */
  1943. X    if (strcmp(bp->b_fname,bp->b_bname)) {
  1944. X        if (bp->b_fname[0] != '\0') {
  1945. X            if (isspace(bp->b_fname[0])) {
  1946. X                /* some of the internally generated buffers
  1947. X                    put other info. in filename slot */
  1948. X                vtputsn(bp->b_fname, NFILEN);
  1949. X            } else {
  1950. X                if (ispunct(bp->b_fname[0]))
  1951. X                    vtputsn(" is \"", 20);
  1952. X                else
  1953. X                    vtputsn(" is file \"", 20);
  1954. X                vtputsn(bp->b_fname, NFILEN);
  1955. X                vtputsn("\"", 20);
  1956. X            }
  1957. X        }
  1958. X    }
  1959. X    vtputc(' ',FALSE);
  1960. X
  1961. X
  1962. X    /* Pad to full width, then go back and overwrite right-end info */
  1963. X    n = term.t_ncol;
  1964. X    while (vtcol < n)
  1965. X        vtputc(lchar,FALSE);
  1966. X        
  1967. X    { /* determine if top line, bottom line, or both are visible */
  1968. X        LINE *lp = wp->w_linep;
  1969. X        int rows = wp->w_ntrows;
  1970. X        char *msg = NULL;
  1971. X        
  1972. X        vtcol = n - 7;  /* strlen(" top ") plus a couple */
  1973. X        while (rows--) {
  1974. X            lp = lforw(lp);
  1975. X            if (lp == wp->w_bufp->b_linep) {
  1976. X                msg = " bot ";
  1977. X                break;
  1978. X            }
  1979. X        }
  1980. X        if (lback(wp->w_linep) == wp->w_bufp->b_linep) {
  1981. X            if (msg) {
  1982. X                if (wp->w_linep == wp->w_bufp->b_linep)
  1983. X                    msg = " emp ";
  1984. X                else 
  1985. X                    msg = " all ";
  1986. X            } else {
  1987. X                msg = " top ";
  1988. X            }
  1989. X        }
  1990. X        if (!msg)
  1991. X            msg = " mid ";
  1992. X        vtputsn(msg,20);
  1993. X    }
  1994. X
  1995. X    if (vtgetc(80) == lchar) {
  1996. X        vtcol = 80;
  1997. X        vtputc('|',FALSE);
  1998. X    }
  1999. }
  2000. X
  2001. upmode()    /* update all the mode lines */
  2002. {
  2003. X    register WINDOW *wp;
  2004. X
  2005. #if     NeWS            /* tell workstation the current modes */
  2006. X        newsreportmodes() ;
  2007. #endif
  2008. X    wp = wheadp;
  2009. X    while (wp != NULL) {
  2010. X        wp->w_flag |= WFMODE;
  2011. X        wp = wp->w_wndp;
  2012. X    }
  2013. }
  2014. X
  2015. /*
  2016. X * Send a command to the terminal to move the hardware cursor to row "row"
  2017. X * and column "col". The row and column arguments are origin 0. Optimize out
  2018. X * random calls. Update "ttrow" and "ttcol".
  2019. X */
  2020. movecursor(row, col)
  2021. {
  2022. #if    ! NeWS        /* "line buffered" */
  2023. X    if (row!=ttrow || col!=ttcol)
  2024. #endif
  2025. X        {
  2026. X            ttrow = row;
  2027. X            ttcol = col;
  2028. X            TTmove(row, col);
  2029. X        }
  2030. }
  2031. X
  2032. X
  2033. X
  2034. #if    NeWS        /* buffer the message line stuff, newsputc is slow */
  2035. #define NEWSBUFSIZ    256
  2036. #undef    TTputc
  2037. #undef    TTflush
  2038. #define TTputc(c)    bufputc(c)
  2039. #define TTflush()    bufputc((char)0)
  2040. X
  2041. bufputc(c)
  2042. char    c ;
  2043. {
  2044. X    static        bufindex = 0 ;
  2045. X    static char    outbuf[NEWSBUFSIZ] ;
  2046. X
  2047. X    if (c == NULL || bufindex >= NEWSBUFSIZ || bufindex >= term.t_ncol) {
  2048. X        outbuf[bufindex] = NULL ;
  2049. X        newsputline(term.t_nrow, outbuf, 7, 0) ;
  2050. X        movecursor(term.t_nrow, strlen(outbuf)) ;
  2051. X        newsflush() ;
  2052. X        bufindex = 0 ;
  2053. X    }
  2054. X    else outbuf[bufindex++] = c ;
  2055. }
  2056. #endif
  2057. X
  2058. X
  2059. /*
  2060. X * Erase the message line. This is a special routine because the message line
  2061. X * is not considered to be part of the virtual screen. It always works
  2062. X * immediately; the terminal buffer is flushed via a call to the flusher.
  2063. X */
  2064. mlerase()
  2065. {
  2066. X    int i;
  2067. X    
  2068. X    if (mpresf == FALSE)
  2069. X        return;
  2070. X    movecursor(term.t_nrow, 0);
  2071. X    if (discmd == FALSE)
  2072. X        return;
  2073. X
  2074. #if    COLOR
  2075. X     TTforg(7);
  2076. X     TTbacg(0);
  2077. #endif
  2078. X    if (eolexist == TRUE)
  2079. X        TTeeol();
  2080. X    else {
  2081. X        for (i = 0; i < term.t_ncol - 1; i++)
  2082. X            TTputc(' ');
  2083. X        movecursor(term.t_nrow, 1);    /* force the move! */
  2084. X        movecursor(term.t_nrow, 0);
  2085. X    }
  2086. X    TTflush();
  2087. X    mpresf = FALSE;
  2088. }
  2089. X
  2090. X
  2091. X
  2092. X
  2093. #ifndef va_dcl     /* then try these out */
  2094. X
  2095. typedef char *va_list;
  2096. #define va_dcl int va_alist;
  2097. #define va_start(list) list = (char *) &va_alist
  2098. #define va_end(list)
  2099. #define va_arg(list, mode) ((mode *)(list += sizeof(mode)))[-1]
  2100. X
  2101. #endif
  2102. X
  2103. dbgwrite(s,x,y,z)
  2104. {
  2105. X    mlwrite(s,x,y,z);
  2106. X    tgetc();
  2107. }
  2108. X
  2109. /*
  2110. X * Write a message into the message line. Keep track of the physical cursor
  2111. X * position. A small class of printf like format items is handled.
  2112. X * Set the "message line" flag TRUE.
  2113. X */
  2114. X
  2115. /* VARARGS */
  2116. mlwrite(fmt, va_alist)
  2117. char *fmt;    /* format string for output */
  2118. va_dcl
  2119. {
  2120. X    register int c;        /* current char in format string */
  2121. X    register va_list ap;    /* ptr to current data field */
  2122. X
  2123. X    /* if we are not currently echoing on the command line, abort this */
  2124. X    if (dotcmdmode == PLAY || discmd == FALSE) {
  2125. X        movecursor(term.t_nrow, 0);
  2126. X        return;
  2127. X    }
  2128. X
  2129. #if    COLOR
  2130. X    /* set up the proper colors for the command line */
  2131. X    TTforg(7);
  2132. X    TTbacg(0);
  2133. #endif
  2134. X
  2135. X    /* if we can not erase to end-of-line, do it manually */
  2136. X    if (eolexist == FALSE) {
  2137. X        mlerase();
  2138. X        TTflush();
  2139. X    }
  2140. X
  2141. X    va_start(ap);
  2142. X
  2143. X    movecursor(term.t_nrow, 0);
  2144. X    while ((c = *fmt) != 0 && ttcol < term.t_ncol-1) {
  2145. X        if (c != '%') {
  2146. X            mlputc(c);
  2147. X        } else {
  2148. X            c = *++fmt;
  2149. X            switch (c) {
  2150. X                case '\0':
  2151. X                    break;
  2152. X                case 'c':
  2153. X                    mlputc(va_arg(ap,int));
  2154. X                    break;
  2155. X
  2156. X                case 'd':
  2157. X                    mlputi(va_arg(ap,int), 10);
  2158. X                    break;
  2159. X
  2160. X                case 'o':
  2161. X                    mlputi(va_arg(ap,int), 8);
  2162. X                    break;
  2163. X
  2164. X                case 'x':
  2165. X                    mlputi(va_arg(ap,int), 16);
  2166. X                    break;
  2167. X
  2168. X                case 'D':
  2169. X                    mlputli(va_arg(ap,long), 10);
  2170. X                    break;
  2171. X
  2172. X                case 's':
  2173. X                    mlputs(va_arg(ap,char *));
  2174. X                    break;
  2175. X
  2176. X                case 'S': {
  2177. X                    int wid = va_arg(ap,int);
  2178. X                    mlputsn(va_arg(ap,char *),wid);
  2179. X                    break;
  2180. X                    }
  2181. X
  2182. X                case 'f':
  2183. X                    mlputf(va_arg(ap,int));
  2184. X                    break;
  2185. X
  2186. X                default:
  2187. X                    mlputc(c);
  2188. X            }
  2189. X        }
  2190. X        fmt++;
  2191. X    }
  2192. X
  2193. X    va_end(ap);
  2194. X
  2195. X    /* if we can, erase to the end of screen */
  2196. X    if (eolexist == TRUE)
  2197. X        TTeeol();
  2198. X    TTflush();
  2199. X    mpresf = TRUE;
  2200. }
  2201. X
  2202. /*    Force a string out to the message line regardless of the
  2203. X    current $discmd setting. This is needed when $debug is TRUE
  2204. X    and for the write-message and clear-message-line commands
  2205. */
  2206. X
  2207. mlforce(s)
  2208. char *s;    /* string to force out */
  2209. {
  2210. X    register oldcmd;    /* original command display flag */
  2211. X
  2212. X    oldcmd = discmd;    /* save the discmd value */
  2213. X    discmd = TRUE;        /* and turn display on */
  2214. X    mlwrite(s);        /* write the string out */
  2215. X    discmd = oldcmd;    /* and restore the original setting */
  2216. }
  2217. X
  2218. /*
  2219. X * Write out a character. Update the physical cursor position. This assumes that
  2220. X * the character has width "1"; if this is not the case
  2221. X * things will get screwed up a little.
  2222. X */
  2223. mlputc(c)
  2224. char c;
  2225. {
  2226. X    if (c == '\r') ttcol = 0;
  2227. X    if (ttcol < term.t_ncol-1) {
  2228. X            TTputc(c);
  2229. X            ++ttcol;
  2230. X    }
  2231. }
  2232. X
  2233. /*
  2234. X * Write out a string. Update the physical cursor position. This assumes that
  2235. X * the characters in the string all have width "1"; if this is not the case
  2236. X * things will get screwed up a little.
  2237. X */
  2238. mlputs(s)
  2239. char *s;
  2240. {
  2241. X    register int c;
  2242. X
  2243. X    while ((c = *s++) != 0) {
  2244. X            mlputc(c);
  2245. X    }
  2246. }
  2247. X
  2248. /* as above, but takes a count for s's length */
  2249. mlputsn(s,n)
  2250. char *s;
  2251. {
  2252. X    register int c;
  2253. X    while ((c = *s++) != 0 && n-- != 0) {
  2254. X            mlputc(c);
  2255. X    }
  2256. }
  2257. X
  2258. /*
  2259. X * Write out an integer, in the specified radix. Update the physical cursor
  2260. X * position.
  2261. X */
  2262. mlputi(i, r)
  2263. {
  2264. X    register int q;
  2265. X    static char hexdigits[] = "0123456789ABCDEF";
  2266. X
  2267. X    if (i < 0) {
  2268. X        i = -i;
  2269. X        mlputc('-');
  2270. X    }
  2271. X
  2272. X    q = i/r;
  2273. X
  2274. X    if (q != 0)
  2275. X        mlputi(q, r);
  2276. X
  2277. X    mlputc(hexdigits[i%r]);
  2278. }
  2279. X
  2280. /*
  2281. X * do the same except as a long integer.
  2282. X */
  2283. mlputli(l, r)
  2284. long l;
  2285. {
  2286. X    register long q;
  2287. X
  2288. X    if (l < 0) {
  2289. X        l = -l;
  2290. X        mlputc('-');
  2291. X    }
  2292. X
  2293. X    q = l/r;
  2294. X
  2295. X    if (q != 0)
  2296. X        mlputli(q, r);
  2297. X
  2298. X    mlputc((int)(l%r)+'0');
  2299. }
  2300. X
  2301. /*
  2302. X *    write out a scaled integer with two decimal places
  2303. X */
  2304. X
  2305. mlputf(s)
  2306. int s;    /* scaled integer to output */
  2307. {
  2308. X    register int i;    /* integer portion of number */
  2309. X    register int f;    /* fractional portion of number */
  2310. X
  2311. X    /* break it up */
  2312. X    i = s / 100;
  2313. X    f = s % 100;
  2314. X
  2315. X    /* send out the integer portion */
  2316. X    mlputi(i, 10);
  2317. X    mlputc('.');
  2318. X    mlputc((f / 10) + '0');
  2319. X    mlputc((f % 10) + '0');
  2320. }    
  2321. X
  2322. #if RAINBOW
  2323. X
  2324. putline(row, col, buf)
  2325. int row, col;
  2326. char buf[];
  2327. {
  2328. X    int n;
  2329. X
  2330. X    n = strlen(buf);
  2331. X    if (col + n - 1 > term.t_ncol)
  2332. X        n = term.t_ncol - col + 1;
  2333. X    Put_Data(row, col, n, buf);
  2334. }
  2335. #endif
  2336. X
  2337. /* Get terminal size from system.
  2338. X   Store number of lines into *heightp and width into *widthp.
  2339. X   If zero or a negative number is stored, the value is not valid.  */
  2340. X
  2341. getscreensize (widthp, heightp)
  2342. int *widthp, *heightp;
  2343. {
  2344. #ifdef TIOCGWINSZ
  2345. X    struct winsize size;
  2346. X    *widthp = 0;
  2347. X    *heightp = 0;
  2348. X    if (ioctl (0, TIOCGWINSZ, &size) < 0)
  2349. X        return;
  2350. X    *widthp = size.ws_col;
  2351. X    *heightp = size.ws_row;
  2352. #else
  2353. X    *widthp = 0;
  2354. X    *heightp = 0;
  2355. #endif
  2356. }
  2357. X
  2358. #ifdef SIGWINCH
  2359. sizesignal ()
  2360. {
  2361. X    int w, h;
  2362. X    extern int errno;
  2363. X    int old_errno = errno;
  2364. X
  2365. X    getscreensize (&w, &h);
  2366. X
  2367. X    if ((h && h-1 != term.t_nrow) || (w && w != term.t_ncol))
  2368. X        newscreensize(h, w);
  2369. X
  2370. X    signal (SIGWINCH, sizesignal);
  2371. X    errno = old_errno;
  2372. }
  2373. X
  2374. newscreensize (h, w)
  2375. int h, w;
  2376. {
  2377. X    /* do the change later */
  2378. X    if (displaying) {
  2379. X        chg_width = w;
  2380. X        chg_height = h;
  2381. X        return;
  2382. X    }
  2383. X    chg_width = chg_height = 0;
  2384. X    if (h - 1 < term.t_mrow)
  2385. X        newlength(TRUE,h);
  2386. X    if (w < term.t_mcol)
  2387. X        newwidth(TRUE,w);
  2388. X
  2389. X    update(TRUE);
  2390. X    return TRUE;
  2391. }
  2392. X
  2393. #endif
  2394. SHAR_EOF
  2395. chmod 0444 display.c ||
  2396. echo 'restore of display.c failed'
  2397. Wc_c="`wc -c < 'display.c'`"
  2398. test 40087 -eq "$Wc_c" ||
  2399.     echo 'display.c: original size 40087, current size' "$Wc_c"
  2400. # ============= dolock.c ==============
  2401. echo 'x - extracting dolock.c (Text)'
  2402. sed 's/^X//' << 'SHAR_EOF' > 'dolock.c' &&
  2403. #if    0
  2404. /*    dolock:    MDBS specific Unix 4.2BSD file locking mechinism
  2405. X        this is not to be distributed generally        */
  2406. X
  2407. #include    <mdbs.h>
  2408. #include    <mdbsio.h>
  2409. #include    <sys/types.h>
  2410. #include    <sys/stat.h>
  2411. X
  2412. /* included by port.h: mdbs.h, mdbsio.h, sys/types.h, sys/stat.h */
  2413. X
  2414. X
  2415. #ifndef bsdunix
  2416. char *dolock(){return(NULL);}
  2417. char *undolock(){return(NULL);}
  2418. #else
  2419. X
  2420. #include <pwd.h>
  2421. #include <errno.h>
  2422. X
  2423. extern int errno;
  2424. X
  2425. #define LOCKDIR ".xlk"
  2426. X
  2427. #define LOCKMSG "LOCK ERROR -- "
  2428. #define LOCKMSZ sizeof(LOCKMSG)
  2429. #define LOCKERR(s) { strcat(lmsg,s); oldumask = umask(oldumask); return(lmsg); }
  2430. X
  2431. /**********************
  2432. X *
  2433. X * dolock -- lock the file fname
  2434. X *
  2435. X * if successful, returns NULL 
  2436. X * if file locked, returns username of person locking the file
  2437. X * if other error, returns "LOCK ERROR: explanation"
  2438. X *
  2439. X * Jon Reid, 2/19/86
  2440. X *
  2441. X *********************/
  2442. X
  2443. BOOL parent = FALSE;
  2444. BOOL tellall = FALSE;
  2445. X
  2446. char *gtname(filespec)        /* get name component of unix-style filespec */
  2447. char *filespec;
  2448. {
  2449. X    char *rname, *rindex();
  2450. X
  2451. X    rname = rindex(filespec,'/');
  2452. SHAR_EOF
  2453. true || echo 'restore of dolock.c failed'
  2454. echo 'End of Vile part 3'
  2455. echo 'File dolock.c is continued in part 4'
  2456. echo 4 > _shar_seq_.tmp
  2457. exit 0
  2458. -- 
  2459.         paul fox, pgf@cayman.com, (617)494-1999
  2460.         Cayman Systems, 26 Landsdowne St., Cambridge, MA 02139
  2461.