home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume1 / 8706 / 13 < prev    next >
Internet Message Format  |  1993-09-01  |  62KB

  1. From mipos3!intelca!oliveb!pyramid!uccba!hal!ncoast!allbery Fri Jun 19 14:06:04 PDT 1987
  2. Article 7 of comp.sources.misc:
  3. Path: td2cad!mipos3!intelca!oliveb!pyramid!uccba!hal!ncoast!allbery
  4. >From: davidsen@steinmetz.UUCP (William E. Davidsen Jr)
  5. Newsgroups: comp.sources.misc
  6. Subject: memacs 3.8i 1 of 11 (Micro-Emacs 3.8i)
  7. Message-ID: <2656@ncoast.UUCP>
  8. Date: 15 Jun 87 18:56:09 GMT
  9. Sender: allbery@ncoast.UUCP
  10. Lines: 2359
  11. Approved: allbery@ncoast.UUCP
  12. X-Archive: comp.sources.misc/8706/13
  13.  
  14. :
  15. #!/bin/sh
  16. # shar+ created from directory /usr2/davidsen/emacs38i
  17. # 13:42 on Thu Jun 11, 1987 by davidsen
  18. echo 'x - ansi.c (text)'
  19. sed << 'E!O!F' 's/^X//' > ansi.c
  20. X/*
  21. X * The routines in this file provide support for ANSI style terminals
  22. X * over a serial line. The serial I/O services are provided by routines in
  23. X * "termio.c". It compiles into nothing if not an ANSI device.
  24. X */
  25. X
  26. X#define    termdef    1            /* don't define "term" external */
  27. X
  28. X#include        <stdio.h>
  29. X#include    "estruct.h"
  30. X#include        "edef.h"
  31. X
  32. X#if     ANSI
  33. X
  34. X#if    AMIGA
  35. X#define NROW    23                      /* Screen size.                 */
  36. X#define NCOL    77                      /* Edit if you want to.         */
  37. X#else
  38. X#define NROW    25                      /* Screen size.                 */
  39. X#define NCOL    80                      /* Edit if you want to.         */
  40. X#endif
  41. X#define    NPAUSE    100            /* # times thru update to pause */
  42. X#define    MARGIN    8            /* size of minimim margin and    */
  43. X#define    SCRSIZ    64            /* scroll size for extended lines */
  44. X#define BEL     0x07                    /* BEL character.               */
  45. X#define ESC     0x1B                    /* ESC character.               */
  46. X
  47. Xextern  int     ttopen();               /* Forward references.          */
  48. Xextern  int     ttgetc();
  49. Xextern  int     ttputc();
  50. Xextern  int     ttflush();
  51. Xextern  int     ttclose();
  52. Xextern  int     ansimove();
  53. Xextern  int     ansieeol();
  54. Xextern  int     ansieeop();
  55. Xextern  int     ansibeep();
  56. Xextern  int     ansiopen();
  57. Xextern    int    ansirev();
  58. Xextern    int    ansiclose();
  59. Xextern    int    ansikopen();
  60. Xextern    int    ansikclose();
  61. Xextern    int    ansicres();
  62. X
  63. X#if    COLOR
  64. Xextern    int    ansifcol();
  65. Xextern    int    ansibcol();
  66. X
  67. Xint    cfcolor = -1;        /* current forground color */
  68. Xint    cbcolor = -1;        /* current background color */
  69. X#endif
  70. X
  71. X/*
  72. X * Standard terminal interface dispatch table. Most of the fields point into
  73. X * "termio" code.
  74. X */
  75. XTERM    term    = {
  76. X    NROW-1,
  77. X        NROW-1,
  78. X        NCOL,
  79. X        NCOL,
  80. X    MARGIN,
  81. X    SCRSIZ,
  82. X    NPAUSE,
  83. X        ansiopen,
  84. X        ansiclose,
  85. X    ansikopen,
  86. X    ansikclose,
  87. X        ttgetc,
  88. X        ttputc,
  89. X        ttflush,
  90. X        ansimove,
  91. X        ansieeol,
  92. X        ansieeop,
  93. X        ansibeep,
  94. X    ansirev,
  95. X    ansicres
  96. X#if    COLOR
  97. X    , ansifcol,
  98. X    ansibcol
  99. X#endif
  100. X};
  101. X
  102. X#if    COLOR
  103. Xansifcol(color)        /* set the current output color */
  104. X
  105. Xint color;    /* color to set */
  106. X
  107. X{
  108. X    if (color == cfcolor)
  109. X        return;
  110. X    ttputc(ESC);
  111. X    ttputc('[');
  112. X    ansiparm(color+30);
  113. X    ttputc('m');
  114. X    cfcolor = color;
  115. X}
  116. X
  117. Xansibcol(color)        /* set the current background color */
  118. X
  119. Xint color;    /* color to set */
  120. X
  121. X{
  122. X    if (color == cbcolor)
  123. X        return;
  124. X    ttputc(ESC);
  125. X    ttputc('[');
  126. X    ansiparm(color+40);
  127. X    ttputc('m');
  128. X        cbcolor = color;
  129. X}
  130. X#endif
  131. X
  132. Xansimove(row, col)
  133. X{
  134. X        ttputc(ESC);
  135. X        ttputc('[');
  136. X        ansiparm(row+1);
  137. X        ttputc(';');
  138. X        ansiparm(col+1);
  139. X        ttputc('H');
  140. X}
  141. X
  142. Xansieeol()
  143. X{
  144. X        ttputc(ESC);
  145. X        ttputc('[');
  146. X        ttputc('K');
  147. X}
  148. X
  149. Xansieeop()
  150. X{
  151. X#if    COLOR
  152. X    ansifcol(gfcolor);
  153. X    ansibcol(gbcolor);
  154. X#endif
  155. X        ttputc(ESC);
  156. X        ttputc('[');
  157. X        ttputc('J');
  158. X}
  159. X
  160. Xansirev(state)        /* change reverse video state */
  161. X
  162. Xint state;    /* TRUE = reverse, FALSE = normal */
  163. X
  164. X{
  165. X#if    COLOR
  166. X    int ftmp, btmp;        /* temporaries for colors */
  167. X#endif
  168. X
  169. X    ttputc(ESC);
  170. X    ttputc('[');
  171. X    ttputc(state ? '7': '0');
  172. X    ttputc('m');
  173. X#if    COLOR
  174. X    if (state == FALSE) {
  175. X        ftmp = cfcolor;
  176. X        btmp = cbcolor;
  177. X        cfcolor = -1;
  178. X        cbcolor = -1;
  179. X        ansifcol(ftmp);
  180. X        ansibcol(btmp);
  181. X    }
  182. X#endif
  183. X}
  184. X
  185. Xansicres()    /* change screen resolution */
  186. X
  187. X{
  188. X    return(TRUE);
  189. X}
  190. X
  191. Xspal(dummy)        /* change pallette settings */
  192. X
  193. X{
  194. X    /* none for now */
  195. X}
  196. X
  197. Xansibeep()
  198. X{
  199. X        ttputc(BEL);
  200. X        ttflush();
  201. X}
  202. X
  203. Xansiparm(n)
  204. Xregister int    n;
  205. X{
  206. X        register int q,r;
  207. X
  208. X        q = n/10;
  209. X        if (q != 0) {
  210. X        r = q/10;
  211. X        if (r != 0) {
  212. X            ttputc((r%10)+'0');
  213. X        }
  214. X        ttputc((q%10) + '0');
  215. X        }
  216. X        ttputc((n%10) + '0');
  217. X}
  218. X
  219. Xansiopen()
  220. X{
  221. X#if     V7 | USG | BSD
  222. X        register char *cp;
  223. X        char *getenv();
  224. X
  225. X        if ((cp = getenv("TERM")) == NULL) {
  226. X                puts("Shell variable TERM not defined!");
  227. X                exit(1);
  228. X        }
  229. X        if (strcmp(cp, "vt100") != 0) {
  230. X                puts("Terminal type not 'vt100'!");
  231. X                exit(1);
  232. X        }
  233. X#endif
  234. X    strcpy(sres, "NORMAL");
  235. X    revexist = TRUE;
  236. X        ttopen();
  237. X}
  238. X
  239. Xansiclose()
  240. X
  241. X{
  242. X#if    COLOR
  243. X    ansifcol(7);
  244. X    ansibcol(0);
  245. X#endif
  246. X    ttclose();
  247. X}
  248. X
  249. Xansikopen()    /* open the keyboard (a noop here) */
  250. X
  251. X{
  252. X}
  253. X
  254. Xansikclose()    /* close the keyboard (a noop here) */
  255. X
  256. X{
  257. X}
  258. X
  259. X#if    FLABEL
  260. Xfnclabel(f, n)        /* label a function key */
  261. X
  262. Xint f,n;    /* default flag, numeric argument [unused] */
  263. X
  264. X{
  265. X    /* on machines with no function keys...don't bother */
  266. X    return(TRUE);
  267. X}
  268. X#endif
  269. X#else
  270. Xansihello()
  271. X{
  272. X}
  273. X#endif
  274. E!O!F
  275. newsize=`wc -c < ansi.c`
  276. if [ $newsize -ne 4489 ]
  277. then echo "File ansi.c was $newsize bytes, 4489 expected"
  278. fi
  279. echo 'x - basic.c (text)'
  280. sed << 'E!O!F' 's/^X//' > basic.c
  281. X/*
  282. X * The routines in this file move the cursor around on the screen. They
  283. X * compute a new value for the cursor, then adjust ".". The display code
  284. X * always updates the cursor location, so only moves between lines, or
  285. X * functions that adjust the top line in the window and invalidate the
  286. X * framing, are hard.
  287. X */
  288. X#include        <stdio.h>
  289. X#include    "estruct.h"
  290. X#include        "edef.h"
  291. X
  292. X/*
  293. X * Move the cursor to the
  294. X * beginning of the current line.
  295. X * Trivial.
  296. X */
  297. Xgotobol(f, n)
  298. X{
  299. X        curwp->w_doto  = 0;
  300. X        return (TRUE);
  301. X}
  302. X
  303. X/*
  304. X * Move the cursor backwards by "n" characters. If "n" is less than zero call
  305. X * "forwchar" to actually do the move. Otherwise compute the new cursor
  306. X * location. Error if you try and move out of the buffer. Set the flag if the
  307. X * line pointer for dot changes.
  308. X */
  309. Xbackchar(f, n)
  310. Xregister int    n;
  311. X{
  312. X        register LINE   *lp;
  313. X
  314. X        if (n < 0)
  315. X                return (forwchar(f, -n));
  316. X        while (n--) {
  317. X                if (curwp->w_doto == 0) {
  318. X                        if ((lp=lback(curwp->w_dotp)) == curbp->b_linep)
  319. X                                return (FALSE);
  320. X                        curwp->w_dotp  = lp;
  321. X                        curwp->w_doto  = llength(lp);
  322. X                        curwp->w_flag |= WFMOVE;
  323. X                } else
  324. X                        curwp->w_doto--;
  325. X        }
  326. X        return (TRUE);
  327. X}
  328. X
  329. X/*
  330. X * Move the cursor to the end of the current line. Trivial. No errors.
  331. X */
  332. Xgotoeol(f, n)
  333. X{
  334. X        curwp->w_doto  = llength(curwp->w_dotp);
  335. X        return (TRUE);
  336. X}
  337. X
  338. X/*
  339. X * Move the cursor forwards by "n" characters. If "n" is less than zero call
  340. X * "backchar" to actually do the move. Otherwise compute the new cursor
  341. X * location, and move ".". Error if you try and move off the end of the
  342. X * buffer. Set the flag if the line pointer for dot changes.
  343. X */
  344. Xforwchar(f, n)
  345. Xregister int    n;
  346. X{
  347. X        if (n < 0)
  348. X                return (backchar(f, -n));
  349. X        while (n--) {
  350. X                if (curwp->w_doto == llength(curwp->w_dotp)) {
  351. X                        if (curwp->w_dotp == curbp->b_linep)
  352. X                                return (FALSE);
  353. X                        curwp->w_dotp  = lforw(curwp->w_dotp);
  354. X                        curwp->w_doto  = 0;
  355. X                        curwp->w_flag |= WFMOVE;
  356. X                } else
  357. X                        curwp->w_doto++;
  358. X        }
  359. X        return (TRUE);
  360. X}
  361. X
  362. Xgotoline(f, n)        /* move to a particular line.
  363. X               argument (n) must be a positive integer for
  364. X               this to actually do anything        */
  365. X
  366. X{
  367. X    register int status;    /* status return */
  368. X    char arg[NSTRING];    /* buffer to hold argument */
  369. X
  370. X    /* get an argument if one doesnt exist */
  371. X    if (f == FALSE) {
  372. X        if ((status = mlreply("Line to GOTO: ", arg, "")) != TRUE) {
  373. X            mlwrite("[Aborted]");
  374. X            return(status);
  375. X        }
  376. X        n = atoi(arg);
  377. X    }
  378. X
  379. X    if (n < 1)        /* if a bogus argument...then leave */
  380. X        return(FALSE);
  381. X
  382. X    /* first, we go to the start of the buffer */
  383. X        curwp->w_dotp  = lforw(curbp->b_linep);
  384. X        curwp->w_doto  = 0;
  385. X    return(forwline(f, n-1));
  386. X}
  387. X
  388. X/*
  389. X * Goto the beginning of the buffer. Massive adjustment of dot. This is
  390. X * considered to be hard motion; it really isn't if the original value of dot
  391. X * is the same as the new value of dot. Normally bound to "M-<".
  392. X */
  393. Xgotobob(f, n)
  394. X{
  395. X        curwp->w_dotp  = lforw(curbp->b_linep);
  396. X        curwp->w_doto  = 0;
  397. X        curwp->w_flag |= WFHARD;
  398. X        return (TRUE);
  399. X}
  400. X
  401. X/*
  402. X * Move to the end of the buffer. Dot is always put at the end of the file
  403. X * (ZJ). The standard screen code does most of the hard parts of update.
  404. X * Bound to "M->".
  405. X */
  406. Xgotoeob(f, n)
  407. X{
  408. X        curwp->w_dotp  = curbp->b_linep;
  409. X        curwp->w_doto  = 0;
  410. X        curwp->w_flag |= WFHARD;
  411. X        return (TRUE);
  412. X}
  413. X
  414. X/*
  415. X * Move forward by full lines. If the number of lines to move is less than
  416. X * zero, call the backward line function to actually do it. The last command
  417. X * controls how the goal column is set. Bound to "C-N". No errors are
  418. X * possible.
  419. X */
  420. Xforwline(f, n)
  421. X{
  422. X        register LINE   *dlp;
  423. X
  424. X        if (n < 0)
  425. X                return (backline(f, -n));
  426. X
  427. X    /* if we are on the last line as we start....fail the command */
  428. X    if (curwp->w_dotp == curbp->b_linep)
  429. X        return(FALSE);
  430. X
  431. X    /* if the last command was not note a line move,
  432. X       reset the goal column */
  433. X        if ((lastflag&CFCPCN) == 0)
  434. X                curgoal = getccol(FALSE);
  435. X
  436. X    /* flag this command as a line move */
  437. X        thisflag |= CFCPCN;
  438. X
  439. X    /* and move the point down */
  440. X        dlp = curwp->w_dotp;
  441. X        while (n-- && dlp!=curbp->b_linep)
  442. X                dlp = lforw(dlp);
  443. X
  444. X    /* reseting the current position */
  445. X        curwp->w_dotp  = dlp;
  446. X        curwp->w_doto  = getgoal(dlp);
  447. X        curwp->w_flag |= WFMOVE;
  448. X        return (TRUE);
  449. X}
  450. X
  451. X/*
  452. X * This function is like "forwline", but goes backwards. The scheme is exactly
  453. X * the same. Check for arguments that are less than zero and call your
  454. X * alternate. Figure out the new line and call "movedot" to perform the
  455. X * motion. No errors are possible. Bound to "C-P".
  456. X */
  457. Xbackline(f, n)
  458. X{
  459. X        register LINE   *dlp;
  460. X
  461. X        if (n < 0)
  462. X                return (forwline(f, -n));
  463. X
  464. X
  465. X    /* if we are on the last line as we start....fail the command */
  466. X    if (lback(curwp->w_dotp) == curbp->b_linep)
  467. X        return(FALSE);
  468. X
  469. X    /* if the last command was not note a line move,
  470. X       reset the goal column */
  471. X        if ((lastflag&CFCPCN) == 0)
  472. X                curgoal = getccol(FALSE);
  473. X
  474. X    /* flag this command as a line move */
  475. X        thisflag |= CFCPCN;
  476. X
  477. X    /* and move the point up */
  478. X        dlp = curwp->w_dotp;
  479. X        while (n-- && lback(dlp)!=curbp->b_linep)
  480. X                dlp = lback(dlp);
  481. X
  482. X    /* reseting the current position */
  483. X        curwp->w_dotp  = dlp;
  484. X        curwp->w_doto  = getgoal(dlp);
  485. X        curwp->w_flag |= WFMOVE;
  486. X        return (TRUE);
  487. X}
  488. X
  489. X#if    WORDPRO
  490. Xgotobop(f, n)    /* go back to the beginning of the current paragraph
  491. X           here we look for a <NL><NL> or <NL><TAB> or <NL><SPACE>
  492. X           combination to delimit the beginning of a paragraph    */
  493. X
  494. Xint f, n;    /* default Flag & Numeric argument */
  495. X
  496. X{
  497. X    register int suc;    /* success of last backchar */
  498. X
  499. X    if (n < 0)    /* the other way...*/
  500. X        return(gotoeop(f, -n));
  501. X
  502. X    while (n-- > 0) {    /* for each one asked for */
  503. X
  504. X        /* first scan back until we are in a word */
  505. X        suc = backchar(FALSE, 1);
  506. X        while (!inword() && suc)
  507. X            suc = backchar(FALSE, 1);
  508. X        curwp->w_doto = 0;    /* and go to the B-O-Line */
  509. X
  510. X        /* and scan back until we hit a <NL><NL> or <NL><TAB>
  511. X           or a <NL><SPACE>                    */
  512. X        while (lback(curwp->w_dotp) != curbp->b_linep)
  513. X            if (llength(curwp->w_dotp) != 0 &&
  514. X                lgetc(curwp->w_dotp, curwp->w_doto) != TAB &&
  515. X                lgetc(curwp->w_dotp, curwp->w_doto) != ' ')
  516. X                curwp->w_dotp = lback(curwp->w_dotp);
  517. X            else
  518. X                break;
  519. X
  520. X        /* and then forward until we are in a word */
  521. X        suc = forwchar(FALSE, 1);
  522. X        while (suc && !inword())
  523. X            suc = forwchar(FALSE, 1);
  524. X    }
  525. X    curwp->w_flag |= WFMOVE;    /* force screen update */
  526. X    return(TRUE);
  527. X}
  528. X
  529. Xgotoeop(f, n)    /* go forword to the end of the current paragraph
  530. X           here we look for a <NL><NL> or <NL><TAB> or <NL><SPACE>
  531. X           combination to delimit the beginning of a paragraph    */
  532. X
  533. Xint f, n;    /* default Flag & Numeric argument */
  534. X
  535. X{
  536. X    register int suc;    /* success of last backchar */
  537. X
  538. X    if (n < 0)    /* the other way...*/
  539. X        return(gotobop(f, -n));
  540. X
  541. X    while (n-- > 0) {    /* for each one asked for */
  542. X
  543. X        /* first scan forward until we are in a word */
  544. X        suc = forwchar(FALSE, 1);
  545. X        while (!inword() && suc)
  546. X            suc = forwchar(FALSE, 1);
  547. X        curwp->w_doto = 0;    /* and go to the B-O-Line */
  548. X        if (suc)    /* of next line if not at EOF */
  549. X            curwp->w_dotp = lforw(curwp->w_dotp);
  550. X
  551. X        /* and scan forword until we hit a <NL><NL> or <NL><TAB>
  552. X           or a <NL><SPACE>                    */
  553. X        while (curwp->w_dotp != curbp->b_linep) {
  554. X            if (llength(curwp->w_dotp) != 0 &&
  555. X                lgetc(curwp->w_dotp, curwp->w_doto) != TAB &&
  556. X                lgetc(curwp->w_dotp, curwp->w_doto) != ' ')
  557. X                curwp->w_dotp = lforw(curwp->w_dotp);
  558. X            else
  559. X                break;
  560. X        }
  561. X
  562. X        /* and then backward until we are in a word */
  563. X        suc = backchar(FALSE, 1);
  564. X        while (suc && !inword()) {
  565. X            suc = backchar(FALSE, 1);
  566. X        }
  567. X        curwp->w_doto = llength(curwp->w_dotp);    /* and to the EOL */
  568. X    }
  569. X    curwp->w_flag |= WFMOVE;    /* force screen update */
  570. X    return(TRUE);
  571. X}
  572. X#endif
  573. X
  574. X/*
  575. X * This routine, given a pointer to a LINE, and the current cursor goal
  576. X * column, return the best choice for the offset. The offset is returned.
  577. X * Used by "C-N" and "C-P".
  578. X */
  579. Xgetgoal(dlp)
  580. Xregister LINE   *dlp;
  581. X{
  582. X        register int    c;
  583. X        register int    col;
  584. X        register int    newcol;
  585. X        register int    dbo;
  586. X
  587. X        col = 0;
  588. X        dbo = 0;
  589. X        while (dbo != llength(dlp)) {
  590. X                c = lgetc(dlp, dbo);
  591. X                newcol = col;
  592. X                if (c == '\t')
  593. X                        newcol |= 0x07;
  594. X                else if (c<0x20 || c==0x7F)
  595. X                        ++newcol;
  596. X                ++newcol;
  597. X                if (newcol > curgoal)
  598. X                        break;
  599. X                col = newcol;
  600. X                ++dbo;
  601. X        }
  602. X        return (dbo);
  603. X}
  604. X
  605. X/*
  606. X * Scroll forward by a specified number of lines, or by a full page if no
  607. X * argument. Bound to "C-V". The "2" in the arithmetic on the window size is
  608. X * the overlap; this value is the default overlap value in ITS EMACS. Because
  609. X * this zaps the top line in the display window, we have to do a hard update.
  610. X */
  611. Xforwpage(f, n)
  612. Xregister int    n;
  613. X{
  614. X        register LINE   *lp;
  615. X
  616. X        if (f == FALSE) {
  617. X                n = curwp->w_ntrows - 2;        /* Default scroll.      */
  618. X                if (n <= 0)                     /* Forget the overlap   */
  619. X                        n = 1;                  /* if tiny window.      */
  620. X        } else if (n < 0)
  621. X                return (backpage(f, -n));
  622. X#if     CVMVAS
  623. X        else                                    /* Convert from pages   */
  624. X                n *= curwp->w_ntrows;           /* to lines.            */
  625. X#endif
  626. X        lp = curwp->w_linep;
  627. X        while (n-- && lp!=curbp->b_linep)
  628. X                lp = lforw(lp);
  629. X        curwp->w_linep = lp;
  630. X        curwp->w_dotp  = lp;
  631. X        curwp->w_doto  = 0;
  632. X        curwp->w_flag |= WFHARD;
  633. X        return (TRUE);
  634. X}
  635. X
  636. X/*
  637. X * This command is like "forwpage", but it goes backwards. The "2", like
  638. X * above, is the overlap between the two windows. The value is from the ITS
  639. X * EMACS manual. Bound to "M-V". We do a hard update for exactly the same
  640. X * reason.
  641. X */
  642. Xbackpage(f, n)
  643. Xregister int    n;
  644. X{
  645. X        register LINE   *lp;
  646. X
  647. X        if (f == FALSE) {
  648. X                n = curwp->w_ntrows - 2;        /* Default scroll.      */
  649. X                if (n <= 0)                     /* Don't blow up if the */
  650. X                        n = 1;                  /* window is tiny.      */
  651. X        } else if (n < 0)
  652. X                return (forwpage(f, -n));
  653. X#if     CVMVAS
  654. X        else                                    /* Convert from pages   */
  655. X                n *= curwp->w_ntrows;           /* to lines.            */
  656. X#endif
  657. X        lp = curwp->w_linep;
  658. X        while (n-- && lback(lp)!=curbp->b_linep)
  659. X                lp = lback(lp);
  660. X        curwp->w_linep = lp;
  661. X        curwp->w_dotp  = lp;
  662. X        curwp->w_doto  = 0;
  663. X        curwp->w_flag |= WFHARD;
  664. X        return (TRUE);
  665. X}
  666. X
  667. X/*
  668. X * Set the mark in the current window to the value of "." in the window. No
  669. X * errors are possible. Bound to "M-.".
  670. X */
  671. Xsetmark(f, n)
  672. X{
  673. X        curwp->w_markp = curwp->w_dotp;
  674. X        curwp->w_marko = curwp->w_doto;
  675. X        mlwrite("[Mark set]");
  676. X        return (TRUE);
  677. X}
  678. X
  679. X/*
  680. X * Swap the values of "." and "mark" in the current window. This is pretty
  681. X * easy, bacause all of the hard work gets done by the standard routine
  682. X * that moves the mark about. The only possible error is "no mark". Bound to
  683. X * "C-X C-X".
  684. X */
  685. Xswapmark(f, n)
  686. X{
  687. X        register LINE   *odotp;
  688. X        register int    odoto;
  689. X
  690. X        if (curwp->w_markp == NULL) {
  691. X                mlwrite("No mark in this window");
  692. X                return (FALSE);
  693. X        }
  694. X        odotp = curwp->w_dotp;
  695. X        odoto = curwp->w_doto;
  696. X        curwp->w_dotp  = curwp->w_markp;
  697. X        curwp->w_doto  = curwp->w_marko;
  698. X        curwp->w_markp = odotp;
  699. X        curwp->w_marko = odoto;
  700. X        curwp->w_flag |= WFMOVE;
  701. X        return (TRUE);
  702. X}
  703. E!O!F
  704. newsize=`wc -c < basic.c`
  705. if [ $newsize -ne 12175 ]
  706. then echo "File basic.c was $newsize bytes, 12175 expected"
  707. fi
  708. echo 'x - bind.c (text)'
  709. sed << 'E!O!F' 's/^X//' > bind.c
  710. X/*    This file is for functions having to do with key bindings,
  711. X    descriptions, help commands and startup file.
  712. X
  713. X    written 11-feb-86 by Daniel Lawrence
  714. X                                */
  715. X
  716. X#include    <stdio.h>
  717. X#include    "estruct.h"
  718. X#include    "edef.h"
  719. X#include    "epath.h"
  720. X
  721. Xextern int meta(), cex(), unarg(), ctrlg(); /* dummy prefix binding functions */
  722. X
  723. Xdeskey(f, n)    /* describe the command for a certain key */
  724. X
  725. X{
  726. X    register int c;        /* command character to describe */
  727. X    register char *ptr;    /* string pointer to scan output strings */
  728. X    register KEYTAB *ktp;    /* pointer into the command table */
  729. X    register int found;    /* matched command flag */
  730. X    register NBIND *nptr;    /* pointer into the name binding table */
  731. X    char outseq[80];    /* output buffer for command sequence */
  732. X
  733. X    /* prompt the user to type us a key to describe */
  734. X    mlwrite(": describe-key ");
  735. X
  736. X    /* get the command sequence to describe */
  737. X    c = getckey(FALSE);            /* get a command sequence */
  738. X
  739. X    /* change it to something we can print as well */
  740. X    cmdstr(c, &outseq[0]);
  741. X
  742. X    /* and dump it out */
  743. X    if (discmd) {
  744. X        ptr = &outseq[0];
  745. X        while (*ptr)
  746. X            TTputc(*ptr++);
  747. X        TTputc(' ');        /* space it out */
  748. X    }
  749. X
  750. X    /* find the right ->function */
  751. X    ktp = &keytab[0];
  752. X    found = FALSE;
  753. X    while (ktp->k_fp != NULL) {
  754. X        if (ktp->k_code == c) {
  755. X            found = TRUE;
  756. X            break;
  757. X        }
  758. X        ++ktp;
  759. X    }
  760. X
  761. X    if (!found)
  762. X        strcpy(outseq,"Not Bound");
  763. X    else {
  764. X        /* match it against the name binding table */
  765. X        nptr = &names[0];
  766. X        strcpy(outseq,"[Bad binding]");
  767. X        while (nptr->n_func != NULL) {
  768. X            if (nptr->n_func == ktp->k_fp) {
  769. X                strcpy(outseq, nptr->n_name);
  770. X                break;
  771. X            }
  772. X            ++nptr;
  773. X        }
  774. X    }
  775. X
  776. X    /* output the command sequence */
  777. X    ptr = &outseq[0];
  778. X    while (*ptr)
  779. X        TTputc(*ptr++);
  780. X}
  781. X
  782. Xcmdstr(c, seq)    /* change a key command to a string we can print out */
  783. X
  784. Xint c;        /* sequence to translate */
  785. Xchar *seq;    /* destination string for sequence */
  786. X
  787. X{
  788. X    char *ptr;    /* pointer into current position in sequence */
  789. X
  790. X    ptr = seq;
  791. X
  792. X    /* apply meta sequence if needed */
  793. X    if (c & META) {
  794. X        *ptr++ = 'M';
  795. X        *ptr++ = '-';
  796. X    }
  797. X
  798. X    /* apply ^X sequence if needed */
  799. X    if (c & CTLX) {
  800. X        *ptr++ = '^';
  801. X        *ptr++ = 'X';
  802. X    }
  803. X
  804. X    /* apply SPEC sequence if needed */
  805. X    if (c & SPEC) {
  806. X        *ptr++ = 'F';
  807. X        *ptr++ = 'N';
  808. X    }
  809. X
  810. X    /* apply control sequence if needed */
  811. X    if (c & CTRL) {
  812. X        *ptr++ = '^';
  813. X    }
  814. X
  815. X    c = c & 255;    /* strip the prefixes */
  816. X
  817. X    /* and output the final sequence */
  818. X
  819. X    *ptr++ = c;
  820. X    *ptr = 0;    /* terminate the string */
  821. X}
  822. X
  823. Xhelp(f, n)    /* give me some help!!!!
  824. X           bring up a fake buffer and read the help file
  825. X           into it with view mode            */
  826. X{
  827. X    register WINDOW *wp;    /* scaning pointer to windows */
  828. X    register BUFFER *bp;    /* buffer pointer to help */
  829. X    char *fname;        /* ptr to file returned by flook() */
  830. X
  831. X    /* first check if we are already here */
  832. X    bp = bfind("emacs.hlp", FALSE, BFINVS);
  833. X
  834. X    if (bp == NULL) {
  835. X        fname = flook(pathname[1], FALSE);
  836. X        if (fname == NULL) {
  837. X            mlwrite("[Help file is not online]");
  838. X            return(FALSE);
  839. X        }
  840. X    }
  841. X
  842. X    /* split the current window to make room for the help stuff */
  843. X    if (splitwind(FALSE, 1) == FALSE)
  844. X            return(FALSE);
  845. X
  846. X    if (bp == NULL) {
  847. X        /* and read the stuff in */
  848. X        if (getfile(fname, FALSE) == FALSE)
  849. X            return(FALSE);
  850. X    } else
  851. X        swbuffer(bp);
  852. X
  853. X    /* make this window in VIEW mode, update all mode lines */
  854. X    curwp->w_bufp->b_mode |= MDVIEW;
  855. X    curwp->w_bufp->b_flag |= BFINVS;
  856. X    wp = wheadp;
  857. X    while (wp != NULL) {
  858. X        wp->w_flag |= WFMODE;
  859. X        wp = wp->w_wndp;
  860. X    }
  861. X    return(TRUE);
  862. X}
  863. X
  864. Xint (*fncmatch(fname))() /* match fname to a function in the names table
  865. X                and return any match or NULL if none        */
  866. X
  867. Xchar *fname;    /* name to attempt to match */
  868. X
  869. X{
  870. X    register NBIND *ffp;    /* pointer to entry in name binding table */
  871. X
  872. X    /* scan through the table, returning any match */
  873. X    ffp = &names[0];
  874. X    while (ffp->n_func != NULL) {
  875. X        if (strcmp(fname, ffp->n_name) == 0)
  876. X            return(ffp->n_func);
  877. X        ++ffp;
  878. X    }
  879. X    return(NULL);
  880. X}
  881. X
  882. X/* bindtokey:    add a new key to the key binding table        */
  883. X
  884. Xbindtokey(f, n)
  885. X
  886. Xint f, n;    /* command arguments [IGNORED] */
  887. X
  888. X{
  889. X    register unsigned int c;/* command key to bind */
  890. X    register (*kfunc)();    /* ptr to the requexted function to bind to */
  891. X    register char *ptr;    /* ptr to dump out input key string */
  892. X    register KEYTAB *ktp;    /* pointer into the command table */
  893. X    register int found;    /* matched command flag */
  894. X    char outseq[80];    /* output buffer for keystroke sequence */
  895. X    int (*getname())();
  896. X
  897. X    /* prompt the user to type in a key to bind */
  898. X    mlwrite(": bind-to-key ");
  899. X
  900. X    /* get the function name to bind it to */
  901. X    kfunc = getname();
  902. X    if (kfunc == NULL) {
  903. X        mlwrite("[No such function]");
  904. X        return(FALSE);
  905. X    }
  906. X    if (discmd) {
  907. X        TTputc(' ');        /* space it out */
  908. X        TTflush();
  909. X    }
  910. X
  911. X    /* get the command sequence to bind */
  912. X    c = getckey((kfunc == meta) || (kfunc == cex) ||
  913. X                (kfunc == unarg) || (kfunc == ctrlg));
  914. X
  915. X    /* change it to something we can print as well */
  916. X    cmdstr(c, &outseq[0]);
  917. X
  918. X    /* and dump it out */
  919. X    if (discmd) {
  920. X        ptr = &outseq[0];
  921. X        while (*ptr)
  922. X            TTputc(*ptr++);
  923. X    }
  924. X
  925. X    /* if the function is a prefix key */
  926. X    if (kfunc == meta || kfunc == cex ||
  927. X        kfunc == unarg || kfunc == ctrlg) {
  928. X
  929. X        /* search for an existing binding for the prefix key */
  930. X        ktp = &keytab[0];
  931. X        found = FALSE;
  932. X        while (ktp->k_fp != NULL) {
  933. X            if (ktp->k_fp == kfunc)
  934. X                unbindchar(ktp->k_code);
  935. X            ++ktp;
  936. X        }
  937. X
  938. X        /* reset the appropriate global prefix variable */
  939. X        if (kfunc == meta)
  940. X            metac = c;
  941. X        if (kfunc == cex)
  942. X            ctlxc = c;
  943. X        if (kfunc == unarg)
  944. X            reptc = c;
  945. X        if (kfunc == ctrlg)
  946. X            abortc = c;
  947. X    }
  948. X
  949. X    /* search the table to see if it exists */
  950. X    ktp = &keytab[0];
  951. X    found = FALSE;
  952. X    while (ktp->k_fp != NULL) {
  953. X        if (ktp->k_code == c) {
  954. X            found = TRUE;
  955. X            break;
  956. X        }
  957. X        ++ktp;
  958. X    }
  959. X
  960. X    if (found) {    /* it exists, just change it then */
  961. X        ktp->k_fp = kfunc;
  962. X    } else {    /* otherwise we need to add it to the end */
  963. X        /* if we run out of binding room, bitch */
  964. X        if (ktp >= &keytab[NBINDS]) {
  965. X            mlwrite("Binding table FULL!");
  966. X            return(FALSE);
  967. X        }
  968. X
  969. X        ktp->k_code = c;    /* add keycode */
  970. X        ktp->k_fp = kfunc;    /* and the function pointer */
  971. X        ++ktp;            /* and make sure the next is null */
  972. X        ktp->k_code = 0;
  973. X        ktp->k_fp = NULL;
  974. X    }
  975. X    return(TRUE);
  976. X}
  977. X
  978. X/* unbindkey:    delete a key from the key binding table    */
  979. X
  980. Xunbindkey(f, n)
  981. X
  982. Xint f, n;    /* command arguments [IGNORED] */
  983. X
  984. X{
  985. X    register int c;        /* command key to unbind */
  986. X    register char *ptr;    /* ptr to dump out input key string */
  987. X    char outseq[80];    /* output buffer for keystroke sequence */
  988. X
  989. X    /* prompt the user to type in a key to unbind */
  990. X    mlwrite(": unbind-key ");
  991. X
  992. X    /* get the command sequence to unbind */
  993. X    c = getckey(FALSE);        /* get a command sequence */
  994. X
  995. X    /* change it to something we can print as well */
  996. X    cmdstr(c, &outseq[0]);
  997. X
  998. X    /* and dump it out */
  999. X    if (discmd) {
  1000. X        ptr = &outseq[0];
  1001. X        while (*ptr)
  1002. X            TTputc(*ptr++);
  1003. X    }
  1004. X
  1005. X    /* if it isn't bound, bitch */
  1006. X    if (unbindchar(c) == FALSE) {
  1007. X        mlwrite("[Key not bound]");
  1008. X        return(FALSE);
  1009. X    }
  1010. X    return(TRUE);
  1011. X}
  1012. X
  1013. Xunbindchar(c)
  1014. X
  1015. Xint c;        /* command key to unbind */
  1016. X
  1017. X{
  1018. X    register KEYTAB *ktp;    /* pointer into the command table */
  1019. X    register KEYTAB *sktp;    /* saved pointer into the command table */
  1020. X    register int found;    /* matched command flag */
  1021. X
  1022. X    /* search the table to see if the key exists */
  1023. X    ktp = &keytab[0];
  1024. X    found = FALSE;
  1025. X    while (ktp->k_fp != NULL) {
  1026. X        if (ktp->k_code == c) {
  1027. X            found = TRUE;
  1028. X            break;
  1029. X        }
  1030. X        ++ktp;
  1031. X    }
  1032. X
  1033. X    /* if it isn't bound, bitch */
  1034. X    if (!found)
  1035. X        return(FALSE);
  1036. X
  1037. X    /* save the pointer and scan to the end of the table */
  1038. X    sktp = ktp;
  1039. X    while (ktp->k_fp != NULL)
  1040. X        ++ktp;
  1041. X    --ktp;        /* backup to the last legit entry */
  1042. X
  1043. X    /* copy the last entry to the current one */
  1044. X    sktp->k_code = ktp->k_code;
  1045. X    sktp->k_fp   = ktp->k_fp;
  1046. X
  1047. X    /* null out the last one */
  1048. X    ktp->k_code = 0;
  1049. X    ktp->k_fp = NULL;
  1050. X    return(TRUE);
  1051. X}
  1052. X
  1053. Xdesbind(f, n)    /* describe bindings
  1054. X           bring up a fake buffer and list the key bindings
  1055. X           into it with view mode            */
  1056. X
  1057. X#if    APROP
  1058. X{
  1059. X    buildlist(TRUE, "");
  1060. X}
  1061. X
  1062. Xapro(f, n)    /* Apropos (List functions that match a substring) */
  1063. X
  1064. X{
  1065. X    char mstring[NSTRING];    /* string to match cmd names to */
  1066. X    int status;        /* status return */
  1067. X
  1068. X    status = mlreply("Apropos string: ", mstring, NSTRING - 1);
  1069. X    if (status != TRUE)
  1070. X        return(status);
  1071. X
  1072. X    return(buildlist(FALSE, mstring));
  1073. X}
  1074. X
  1075. Xbuildlist(type, mstring)  /* build a binding list (limited or full) */
  1076. X
  1077. Xint type;    /* true = full list,   false = partial list */
  1078. Xchar *mstring;    /* match string if a partial list */
  1079. X
  1080. X#endif
  1081. X{
  1082. X#if    ST520 & LATTICE
  1083. X#define    register        
  1084. X#endif
  1085. X    register WINDOW *wp;    /* scanning pointer to windows */
  1086. X    register KEYTAB *ktp;    /* pointer into the command table */
  1087. X    register NBIND *nptr;    /* pointer into the name binding table */
  1088. X    register BUFFER *bp;    /* buffer to put binding list into */
  1089. X    char *strp;        /* pointer int string to send */
  1090. X    int cpos;        /* current position to use in outseq */
  1091. X    char outseq[80];    /* output buffer for keystroke sequence */
  1092. X
  1093. X    /* split the current window to make room for the binding list */
  1094. X    if (splitwind(FALSE, 1) == FALSE)
  1095. X            return(FALSE);
  1096. X
  1097. X    /* and get a buffer for it */
  1098. X    bp = bfind("Binding list", TRUE, 0);
  1099. X    if (bp == NULL || bclear(bp) == FALSE) {
  1100. X        mlwrite("Can not display binding list");
  1101. X        return(FALSE);
  1102. X    }
  1103. X
  1104. X    /* let us know this is in progress */
  1105. X    mlwrite("[Building binding list]");
  1106. X
  1107. X    /* disconect the current buffer */
  1108. X        if (--curbp->b_nwnd == 0) {             /* Last use.            */
  1109. X                curbp->b_dotp  = curwp->w_dotp;
  1110. X                curbp->b_doto  = curwp->w_doto;
  1111. X                curbp->b_markp = curwp->w_markp;
  1112. X                curbp->b_marko = curwp->w_marko;
  1113. X        }
  1114. X
  1115. X    /* connect the current window to this buffer */
  1116. X    curbp = bp;    /* make this buffer current in current window */
  1117. X    bp->b_mode = 0;        /* no modes active in binding list */
  1118. X    bp->b_nwnd++;        /* mark us as more in use */
  1119. X    wp = curwp;
  1120. X    wp->w_bufp = bp;
  1121. X    wp->w_linep = bp->b_linep;
  1122. X    wp->w_flag = WFHARD|WFFORCE;
  1123. X    wp->w_dotp = bp->b_dotp;
  1124. X    wp->w_doto = bp->b_doto;
  1125. X    wp->w_markp = NULL;
  1126. X    wp->w_marko = 0;
  1127. X
  1128. X    /* build the contents of this window, inserting it line by line */
  1129. X    nptr = &names[0];
  1130. X    while (nptr->n_func != NULL) {
  1131. X
  1132. X        /* add in the command name */
  1133. X        strcpy(outseq, nptr->n_name);
  1134. X        cpos = strlen(outseq);
  1135. X        
  1136. X#if    APROP
  1137. X        /* if we are executing an apropos command..... */
  1138. X        if (type == FALSE &&
  1139. X            /* and current string doesn't include the search string */
  1140. X            strinc(outseq, mstring) == FALSE)
  1141. X            goto fail;
  1142. X#endif
  1143. X        /* search down any keys bound to this */
  1144. X        ktp = &keytab[0];
  1145. X        while (ktp->k_fp != NULL) {
  1146. X            if (ktp->k_fp == nptr->n_func) {
  1147. X                /* padd out some spaces */
  1148. X                while (cpos < 25)
  1149. X                    outseq[cpos++] = ' ';
  1150. X
  1151. X                /* add in the command sequence */
  1152. X                cmdstr(ktp->k_code, &outseq[cpos]);
  1153. X                while (outseq[cpos] != 0)
  1154. X                    ++cpos;
  1155. X
  1156. X                /* and add it as a line into the buffer */
  1157. X                strp = &outseq[0];
  1158. X                while (*strp != 0)
  1159. X                    linsert(1, *strp++);
  1160. X                lnewline();
  1161. X
  1162. X                cpos = 0;    /* and clear the line */
  1163. X            }
  1164. X            ++ktp;
  1165. X        }
  1166. X
  1167. X        /* if no key was bound, we need to dump it anyway */
  1168. X        if (cpos > 0) {
  1169. X            outseq[cpos] = 0;
  1170. X            strp = &outseq[0];
  1171. X            while (*strp != 0)
  1172. X                linsert(1, *strp++);
  1173. X            lnewline();
  1174. X        }
  1175. X
  1176. Xfail:        /* and on to the next name */
  1177. X        ++nptr;
  1178. X    }
  1179. X
  1180. X    curwp->w_bufp->b_mode |= MDVIEW;/* put this buffer view mode */
  1181. X    curbp->b_flag &= ~BFCHG;    /* don't flag this as a change */
  1182. X    wp->w_dotp = lforw(bp->b_linep);/* back to the beginning */
  1183. X    wp->w_doto = 0;
  1184. X    wp = wheadp;            /* and update ALL mode lines */
  1185. X    while (wp != NULL) {
  1186. X        wp->w_flag |= WFMODE;
  1187. X        wp = wp->w_wndp;
  1188. X    }
  1189. X    mlwrite("");    /* clear the mode line */
  1190. X    return(TRUE);
  1191. X}
  1192. X
  1193. X#if    APROP
  1194. Xstrinc(source, sub)    /* does source include sub? */
  1195. X
  1196. Xchar *source;    /* string to search in */
  1197. Xchar *sub;    /* substring to look for */
  1198. X
  1199. X{
  1200. X    char *sp;    /* ptr into source */
  1201. X    char *nxtsp;    /* next ptr into source */
  1202. X    char *tp;    /* ptr into substring */
  1203. X
  1204. X    /* for each character in the source string */
  1205. X    sp = source;
  1206. X    while (*sp) {
  1207. X        tp = sub;
  1208. X        nxtsp = sp;
  1209. X
  1210. X        /* is the substring here? */
  1211. X        while (*tp) {
  1212. X            if (*nxtsp++ != *tp)
  1213. X                break;
  1214. X            else
  1215. X                tp++;
  1216. X        }
  1217. X
  1218. X        /* yes, return a success */
  1219. X        if (*tp == 0)
  1220. X            return(TRUE);
  1221. X
  1222. X        /* no, onward */
  1223. X        sp++;
  1224. X    }
  1225. X    return(FALSE);
  1226. X}
  1227. X#endif
  1228. X
  1229. X/* get a command key sequence from the keyboard    */
  1230. X
  1231. Xunsigned int getckey(mflag)
  1232. X
  1233. Xint mflag;    /* going for a meta sequence? */
  1234. X
  1235. X{
  1236. X    register unsigned int c;    /* character fetched */
  1237. X#if    MSC
  1238. X    register unsigned char *tp;    /* pointer into the token */
  1239. X#else
  1240. X    register char *tp;        /* pointer into the token */
  1241. X#endif
  1242. X    char tok[NSTRING];        /* command incoming */
  1243. X
  1244. X    /* check to see if we are executing a command line */
  1245. X    if (clexec) {
  1246. X        macarg(tok);    /* get the next token */
  1247. X
  1248. X        /* parse it up */
  1249. X        tp = &tok[0];
  1250. X        c = 0;
  1251. X
  1252. X        /* first, the META prefix */
  1253. X        if (*tp == 'M' && *(tp+1) == '-') {
  1254. X            c = META;
  1255. X            tp += 2;
  1256. X        }
  1257. X
  1258. X        /* next the function prefix */
  1259. X        if (*tp == 'F' && *(tp+1) == 'N') {
  1260. X            c |= SPEC;
  1261. X            tp += 2;
  1262. X        }
  1263. X
  1264. X        /* control-x as well... */
  1265. X        if (*tp == '^' && *(tp+1) == 'X') {
  1266. X            c |= CTLX;
  1267. X            tp += 2;
  1268. X        }
  1269. X
  1270. X        /* a control char? */
  1271. X        if (*tp == '^' && *(tp+1) != 0) {
  1272. X            c |= CTRL;
  1273. X            ++tp;
  1274. X        }
  1275. X
  1276. X        /* make sure we are not lower case (not with function keys)*/
  1277. X        if (c >= 'a' && c <= 'z' && !(c & SPEC))
  1278. X            c -= 32;
  1279. X
  1280. X        /* the final sequence... */
  1281. X        c |= *tp;
  1282. X
  1283. X        return(c);
  1284. X    }
  1285. X
  1286. X    /* or the normal way */
  1287. X    if (mflag)
  1288. X        c = get1key();
  1289. X    else
  1290. X        c = getcmd();
  1291. X    return(c);
  1292. X}
  1293. X
  1294. X/* execute the startup file */
  1295. X
  1296. Xstartup(sfname)
  1297. X
  1298. Xchar *sfname;    /* name of startup file (null if default) */
  1299. X
  1300. X{
  1301. X    char *fname;    /* resulting file name to execute */
  1302. X
  1303. X    /* look up the startup file */
  1304. X    if (*sfname != 0)
  1305. X        fname = flook(sfname, TRUE);
  1306. X    else
  1307. X        fname = flook(pathname[0], TRUE);
  1308. X
  1309. X    /* if it isn't around, don't sweat it */
  1310. X    if (fname == NULL)
  1311. X        return(TRUE);
  1312. X
  1313. X    /* otherwise, execute the sucker */
  1314. X    return(dofile(fname));
  1315. X}
  1316. X
  1317. X/*    Look up the existance of a file along the normal or PATH
  1318. X    environment variable. Look first in the HOME directory if
  1319. X    asked and possible
  1320. X*/
  1321. X
  1322. Xchar *flook(fname, hflag)
  1323. X
  1324. Xchar *fname;    /* base file name to search for */
  1325. Xint hflag;    /* Look in the HOME environment variable first? */
  1326. X
  1327. X{
  1328. X    register char *home;    /* path to home directory */
  1329. X    register char *path;    /* environmental PATH variable */
  1330. X    register char *sp;    /* pointer into path spec */
  1331. X    register int i;        /* index */
  1332. X    register int status;    /* return status */
  1333. X    static char fspec[NSTRING];    /* full path spec to search */
  1334. X    char *getenv();
  1335. X
  1336. X#if    ((MSDOS) & (LATTICE | AZTEC | MSC)) | V7 | USG | BSD
  1337. X
  1338. X    if (hflag) {
  1339. X        home = getenv("HOME");
  1340. X        if (home != NULL) {
  1341. X            /* build home dir file spec */
  1342. X            strcpy(fspec, home);
  1343. X            strcat(fspec, "/");
  1344. X            strcat(fspec, fname);
  1345. X
  1346. X            /* and try it out */
  1347. X            status = ffropen(fspec);
  1348. X            if (status == FIOSUC) {
  1349. X                ffclose();
  1350. X                return(fspec);
  1351. X            }
  1352. X        }
  1353. X    }
  1354. X
  1355. X    /* get the PATH variable */
  1356. X    path = getenv("PATH");
  1357. X    if (path != NULL)
  1358. X        while (*path) {
  1359. X
  1360. X            /* build next possible file spec */
  1361. X            sp = fspec;
  1362. X            while (*path && (*path != PATHCHR))
  1363. X                *sp++ = *path++;
  1364. X            *sp++ = '/';
  1365. X            *sp = 0;
  1366. X            strcat(fspec, fname);
  1367. X
  1368. X            /* and try it out */
  1369. X            status = ffropen(fspec);
  1370. X            if (status == FIOSUC) {
  1371. X                ffclose();
  1372. X                return(fspec);
  1373. X            }
  1374. X
  1375. X            if (*path == PATHCHR)
  1376. X                ++path;
  1377. X        }
  1378. X#endif
  1379. X
  1380. X    /* look it up via the old table method */
  1381. X    for (i=2; i < NPNAMES; i++) {
  1382. X        strcpy(fspec, pathname[i]);
  1383. X        strcat(fspec, fname);
  1384. X
  1385. X        /* and try it out */
  1386. X        status = ffropen(fspec);
  1387. X        if (status == FIOSUC) {
  1388. X            ffclose();
  1389. X            return(fspec);
  1390. X        }
  1391. X    }
  1392. X
  1393. X    return(NULL);    /* no such luck */
  1394. X}
  1395. X
  1396. E!O!F
  1397. newsize=`wc -c < bind.c`
  1398. if [ $newsize -ne 15191 ]
  1399. then echo "File bind.c was $newsize bytes, 15191 expected"
  1400. fi
  1401. echo 'x - buffer.c (text)'
  1402. sed << 'E!O!F' 's/^X//' > buffer.c
  1403. X/*
  1404. X * Buffer management.
  1405. X * Some of the functions are internal,
  1406. X * and some are actually attached to user
  1407. X * keys. Like everyone else, they set hints
  1408. X * for the display system.
  1409. X */
  1410. X#include        <stdio.h>
  1411. X#include    "estruct.h"
  1412. X#include        "edef.h"
  1413. X
  1414. X/*
  1415. X * Attach a buffer to a window. The
  1416. X * values of dot and mark come from the buffer
  1417. X * if the use count is 0. Otherwise, they come
  1418. X * from some other window.
  1419. X */
  1420. Xusebuffer(f, n)
  1421. X{
  1422. X        register BUFFER *bp;
  1423. X        register int    s;
  1424. X        char            bufn[NBUFN];
  1425. X
  1426. X        if ((s=mlreply("Use buffer: ", bufn, NBUFN)) != TRUE)
  1427. X                return (s);
  1428. X        if ((bp=bfind(bufn, TRUE, 0)) == NULL)
  1429. X                return (FALSE);
  1430. X    return(swbuffer(bp));
  1431. X}
  1432. X
  1433. Xnextbuffer(f, n)    /* switch to the next buffer in the buffer list */
  1434. X
  1435. Xint f, n;    /* default flag, numeric argument */
  1436. X{
  1437. X    register BUFFER *bp;    /* eligable buffer to switch to*/
  1438. X    register BUFFER *bbp;    /* eligable buffer to switch to*/
  1439. X
  1440. X    /* make sure the arg is legit */
  1441. X    if (f == FALSE)
  1442. X        n = 1;
  1443. X    if (n < 1)
  1444. X        return(FALSE);
  1445. X
  1446. X    bbp = curbp;
  1447. X    while (n-- > 0) {
  1448. X        /* advance to the next buffer */
  1449. X        bp = bbp->b_bufp;
  1450. X
  1451. X        /* cycle through the buffers to find an eligable one */
  1452. X        while (bp == NULL || bp->b_flag & BFINVS) {
  1453. X            if (bp == NULL)
  1454. X                bp = bheadp;
  1455. X            else
  1456. X                bp = bp->b_bufp;
  1457. X
  1458. X            /* don't get caught in an infinite loop! */
  1459. X            if (bp == bbp)
  1460. X                return(FALSE);
  1461. X
  1462. X        }        
  1463. X
  1464. X        bbp = bp;
  1465. X    }
  1466. X
  1467. X    return(swbuffer(bp));
  1468. X}
  1469. X
  1470. Xswbuffer(bp)    /* make buffer BP current */
  1471. X
  1472. XBUFFER *bp;
  1473. X
  1474. X{
  1475. X        register WINDOW *wp;
  1476. X
  1477. X        if (--curbp->b_nwnd == 0) {             /* Last use.            */
  1478. X                curbp->b_dotp  = curwp->w_dotp;
  1479. X                curbp->b_doto  = curwp->w_doto;
  1480. X                curbp->b_markp = curwp->w_markp;
  1481. X                curbp->b_marko = curwp->w_marko;
  1482. X        }
  1483. X        curbp = bp;                             /* Switch.              */
  1484. X    if (curbp->b_active != TRUE) {        /* buffer not active yet*/
  1485. X        /* read it in and activate it */
  1486. X        readin(curbp->b_fname, TRUE);
  1487. X        curbp->b_dotp = lforw(curbp->b_linep);
  1488. X        curbp->b_doto = 0;
  1489. X        curbp->b_active = TRUE;
  1490. X    }
  1491. X        curwp->w_bufp  = bp;
  1492. X        curwp->w_linep = bp->b_linep;           /* For macros, ignored. */
  1493. X        curwp->w_flag |= WFMODE|WFFORCE|WFHARD; /* Quite nasty.         */
  1494. X        if (bp->b_nwnd++ == 0) {                /* First use.           */
  1495. X                curwp->w_dotp  = bp->b_dotp;
  1496. X                curwp->w_doto  = bp->b_doto;
  1497. X                curwp->w_markp = bp->b_markp;
  1498. X                curwp->w_marko = bp->b_marko;
  1499. X                return (TRUE);
  1500. X        }
  1501. X        wp = wheadp;                            /* Look for old.        */
  1502. X        while (wp != NULL) {
  1503. X                if (wp!=curwp && wp->w_bufp==bp) {
  1504. X                        curwp->w_dotp  = wp->w_dotp;
  1505. X                        curwp->w_doto  = wp->w_doto;
  1506. X                        curwp->w_markp = wp->w_markp;
  1507. X                        curwp->w_marko = wp->w_marko;
  1508. X                        break;
  1509. X                }
  1510. X                wp = wp->w_wndp;
  1511. X        }
  1512. X        return (TRUE);
  1513. X}
  1514. X
  1515. X/*
  1516. X * Dispose of a buffer, by name.
  1517. X * Ask for the name. Look it up (don't get too
  1518. X * upset if it isn't there at all!). Get quite upset
  1519. X * if the buffer is being displayed. Clear the buffer (ask
  1520. X * if the buffer has been changed). Then free the header
  1521. X * line and the buffer header. Bound to "C-X K".
  1522. X */
  1523. Xkillbuffer(f, n)
  1524. X
  1525. X{
  1526. X    register BUFFER *bp;
  1527. X        register int    s;
  1528. X        char bufn[NBUFN];
  1529. X
  1530. X        if ((s=mlreply("Kill buffer: ", bufn, NBUFN)) != TRUE)
  1531. X                return(s);
  1532. X        if ((bp=bfind(bufn, FALSE, 0)) == NULL) /* Easy if unknown.     */
  1533. X                return (TRUE);
  1534. X    if(bp->b_flag & BFINVS)        /* Deal with special buffers    */
  1535. X            return (TRUE);        /* by doing nothing.    */
  1536. X    return(zotbuf(bp));
  1537. X}
  1538. X
  1539. Xzotbuf(bp)    /* kill the buffer pointed to by bp */
  1540. X
  1541. Xregister BUFFER *bp;
  1542. X
  1543. X{
  1544. X        register BUFFER *bp1;
  1545. X        register BUFFER *bp2;
  1546. X        register int    s;
  1547. X
  1548. X        if (bp->b_nwnd != 0) {                  /* Error if on screen.  */
  1549. X                mlwrite("Buffer is being displayed");
  1550. X                return (FALSE);
  1551. X        }
  1552. X        if ((s=bclear(bp)) != TRUE)             /* Blow text away.      */
  1553. X                return (s);
  1554. X        free((char *) bp->b_linep);             /* Release header line. */
  1555. X        bp1 = NULL;                             /* Find the header.     */
  1556. X        bp2 = bheadp;
  1557. X        while (bp2 != bp) {
  1558. X                bp1 = bp2;
  1559. X                bp2 = bp2->b_bufp;
  1560. X        }
  1561. X        bp2 = bp2->b_bufp;                      /* Next one in chain.   */
  1562. X        if (bp1 == NULL)                        /* Unlink it.           */
  1563. X                bheadp = bp2;
  1564. X        else
  1565. X                bp1->b_bufp = bp2;
  1566. X        free((char *) bp);                      /* Release buffer block */
  1567. X        return (TRUE);
  1568. X}
  1569. X
  1570. Xnamebuffer(f,n)        /*    Rename the current buffer    */
  1571. X
  1572. Xint f, n;        /* default Flag & Numeric arg */
  1573. X
  1574. X{
  1575. X    register BUFFER *bp;    /* pointer to scan through all buffers */
  1576. X    char bufn[NBUFN];    /* buffer to hold buffer name */
  1577. X
  1578. X    /* prompt for and get the new buffer name */
  1579. Xask:    if (mlreply("Change buffer name to: ", bufn, NBUFN) != TRUE)
  1580. X        return(FALSE);
  1581. X
  1582. X    /* and check for duplicates */
  1583. X    bp = bheadp;
  1584. X    while (bp != NULL) {
  1585. X        if (bp != curbp) {
  1586. X            /* if the names the same */
  1587. X            if (strcmp(bufn, bp->b_bname) == 0)
  1588. X                goto ask;  /* try again */
  1589. X        }
  1590. X        bp = bp->b_bufp;    /* onward */
  1591. X    }
  1592. X
  1593. X    strcpy(curbp->b_bname, bufn);    /* copy buffer name to structure */
  1594. X    curwp->w_flag |= WFMODE;    /* make mode line replot */
  1595. X    mlerase();
  1596. X    return(TRUE);
  1597. X}
  1598. X
  1599. X/*
  1600. X    List all of the active buffers.  First update the special
  1601. X    buffer that holds the list.  Next make sure at least 1
  1602. X    window is displaying the buffer list, splitting the screen
  1603. X    if this is what it takes.  Lastly, repaint all of the
  1604. X    windows that are displaying the list.  Bound to "C-X C-B". 
  1605. X    A numeric argument forces it to list invisable buffers as
  1606. X    well.
  1607. X*/
  1608. X
  1609. Xlistbuffers(f, n)
  1610. X{
  1611. X        register WINDOW *wp;
  1612. X        register BUFFER *bp;
  1613. X        register int    s;
  1614. X
  1615. X        if ((s=makelist(f)) != TRUE)
  1616. X                return (s);
  1617. X        if (blistp->b_nwnd == 0) {              /* Not on screen yet.   */
  1618. X                if ((wp=wpopup()) == NULL)
  1619. X                        return (FALSE);
  1620. X                bp = wp->w_bufp;
  1621. X                if (--bp->b_nwnd == 0) {
  1622. X                        bp->b_dotp  = wp->w_dotp;
  1623. X                        bp->b_doto  = wp->w_doto;
  1624. X                        bp->b_markp = wp->w_markp;
  1625. X                        bp->b_marko = wp->w_marko;
  1626. X                }
  1627. X                wp->w_bufp  = blistp;
  1628. X                ++blistp->b_nwnd;
  1629. X        }
  1630. X        wp = wheadp;
  1631. X        while (wp != NULL) {
  1632. X                if (wp->w_bufp == blistp) {
  1633. X                        wp->w_linep = lforw(blistp->b_linep);
  1634. X                        wp->w_dotp  = lforw(blistp->b_linep);
  1635. X                        wp->w_doto  = 0;
  1636. X                        wp->w_markp = NULL;
  1637. X                        wp->w_marko = 0;
  1638. X                        wp->w_flag |= WFMODE|WFHARD;
  1639. X                }
  1640. X                wp = wp->w_wndp;
  1641. X        }
  1642. X        return (TRUE);
  1643. X}
  1644. X
  1645. X/*
  1646. X * This routine rebuilds the
  1647. X * text in the special secret buffer
  1648. X * that holds the buffer list. It is called
  1649. X * by the list buffers command. Return TRUE
  1650. X * if everything works. Return FALSE if there
  1651. X * is an error (if there is no memory). Iflag
  1652. X * indecates weather to list hidden buffers.
  1653. X */
  1654. Xmakelist(iflag)
  1655. X
  1656. Xint iflag;    /* list hidden buffer flag */
  1657. X
  1658. X{
  1659. X        register char   *cp1;
  1660. X        register char   *cp2;
  1661. X        register int    c;
  1662. X        register BUFFER *bp;
  1663. X        register LINE   *lp;
  1664. X        register int    s;
  1665. X    register int    i;
  1666. X        long nbytes;        /* # of bytes in current buffer */
  1667. X        char b[7+1];
  1668. X        char line[128];
  1669. X
  1670. X        blistp->b_flag &= ~BFCHG;               /* Don't complain!      */
  1671. X        if ((s=bclear(blistp)) != TRUE)         /* Blow old text away   */
  1672. X                return (s);
  1673. X        strcpy(blistp->b_fname, "");
  1674. X        if (addline("AC MODES        Size Buffer        File") == FALSE
  1675. X        ||  addline("-- -----        ---- ------        ----") == FALSE)
  1676. X                return (FALSE);
  1677. X        bp = bheadp;                            /* For all buffers      */
  1678. X
  1679. X    /* build line to report global mode settings */
  1680. X    cp1 = &line[0];
  1681. X    *cp1++ = ' ';
  1682. X    *cp1++ = ' ';
  1683. X    *cp1++ = ' ';
  1684. X
  1685. X    /* output the mode codes */
  1686. X    for (i = 0; i < NUMMODES; i++)
  1687. X        if (gmode & (1 << i))
  1688. X            *cp1++ = modecode[i];
  1689. X        else
  1690. X            *cp1++ = '.';
  1691. X    strcpy(cp1, "         Global Modes");
  1692. X    if (addline(line) == FALSE)
  1693. X        return(FALSE);
  1694. X
  1695. X    /* output the list of buffers */
  1696. X        while (bp != NULL) {
  1697. X        /* skip invisable buffers if iflag is false */
  1698. X                if (((bp->b_flag&BFINVS) != 0) && (iflag != TRUE)) {
  1699. X                        bp = bp->b_bufp;
  1700. X                        continue;
  1701. X                }
  1702. X                cp1 = &line[0];                 /* Start at left edge   */
  1703. X
  1704. X        /* output status of ACTIVE flag (has the file been read in? */
  1705. X                if (bp->b_active == TRUE)    /* "@" if activated       */
  1706. X                        *cp1++ = '@';
  1707. X                else
  1708. X                        *cp1++ = ' ';
  1709. X
  1710. X        /* output status of changed flag */
  1711. X                if ((bp->b_flag&BFCHG) != 0)    /* "*" if changed       */
  1712. X                        *cp1++ = '*';
  1713. X                else
  1714. X                        *cp1++ = ' ';
  1715. X                *cp1++ = ' ';                   /* Gap.                 */
  1716. X
  1717. X        /* output the mode codes */
  1718. X        for (i = 0; i < NUMMODES; i++) {
  1719. X            if (bp->b_mode & (1 << i))
  1720. X                *cp1++ = modecode[i];
  1721. X            else
  1722. X                *cp1++ = '.';
  1723. X        }
  1724. X                *cp1++ = ' ';                   /* Gap.                 */
  1725. X                nbytes = 0L;                    /* Count bytes in buf.  */
  1726. X                lp = lforw(bp->b_linep);
  1727. X                while (lp != bp->b_linep) {
  1728. X                        nbytes += (long)llength(lp)+1L;
  1729. X                        lp = lforw(lp);
  1730. X                }
  1731. X                ltoa(b, 7, nbytes);             /* 6 digit buffer size. */
  1732. X                cp2 = &b[0];
  1733. X                while ((c = *cp2++) != 0)
  1734. X                        *cp1++ = c;
  1735. X                *cp1++ = ' ';                   /* Gap.                 */
  1736. X                cp2 = &bp->b_bname[0];          /* Buffer name          */
  1737. X                while ((c = *cp2++) != 0)
  1738. X                        *cp1++ = c;
  1739. X                cp2 = &bp->b_fname[0];          /* File name            */
  1740. X                if (*cp2 != 0) {
  1741. X                        while (cp1 < &line[2+1+5+1+6+1+NBUFN])
  1742. X                                *cp1++ = ' ';
  1743. X                        while ((c = *cp2++) != 0) {
  1744. X                                if (cp1 < &line[128-1])
  1745. X                                        *cp1++ = c;
  1746. X                        }
  1747. X                }
  1748. X                *cp1 = 0;                       /* Add to the buffer.   */
  1749. X                if (addline(line) == FALSE)
  1750. X                        return (FALSE);
  1751. X                bp = bp->b_bufp;
  1752. X        }
  1753. X        return (TRUE);                          /* All done             */
  1754. X}
  1755. X
  1756. Xltoa(buf, width, num)
  1757. X
  1758. Xchar   buf[];
  1759. Xint    width;
  1760. Xlong   num;
  1761. X
  1762. X{
  1763. X        buf[width] = 0;                         /* End of string.       */
  1764. X        while (num >= 10) {                     /* Conditional digits.  */
  1765. X                buf[--width] = (int)(num%10L) + '0';
  1766. X                num /= 10L;
  1767. X        }
  1768. X        buf[--width] = (int)num + '0';          /* Always 1 digit.      */
  1769. X        while (width != 0)                      /* Pad with blanks.     */
  1770. X                buf[--width] = ' ';
  1771. X}
  1772. X
  1773. X/*
  1774. X * The argument "text" points to
  1775. X * a string. Append this line to the
  1776. X * buffer list buffer. Handcraft the EOL
  1777. X * on the end. Return TRUE if it worked and
  1778. X * FALSE if you ran out of room.
  1779. X */
  1780. Xaddline(text)
  1781. Xchar    *text;
  1782. X{
  1783. X        register LINE   *lp;
  1784. X        register int    i;
  1785. X        register int    ntext;
  1786. X
  1787. X        ntext = strlen(text);
  1788. X        if ((lp=lalloc(ntext)) == NULL)
  1789. X                return (FALSE);
  1790. X        for (i=0; i<ntext; ++i)
  1791. X                lputc(lp, i, text[i]);
  1792. X        blistp->b_linep->l_bp->l_fp = lp;       /* Hook onto the end    */
  1793. X        lp->l_bp = blistp->b_linep->l_bp;
  1794. X        blistp->b_linep->l_bp = lp;
  1795. X        lp->l_fp = blistp->b_linep;
  1796. X        if (blistp->b_dotp == blistp->b_linep)  /* If "." is at the end */
  1797. X                blistp->b_dotp = lp;            /* move it to new line  */
  1798. X        return (TRUE);
  1799. X}
  1800. X
  1801. X/*
  1802. X * Look through the list of
  1803. X * buffers. Return TRUE if there
  1804. X * are any changed buffers. Buffers
  1805. X * that hold magic internal stuff are
  1806. X * not considered; who cares if the
  1807. X * list of buffer names is hacked.
  1808. X * Return FALSE if no buffers
  1809. X * have been changed.
  1810. X */
  1811. Xanycb()
  1812. X{
  1813. X        register BUFFER *bp;
  1814. X
  1815. X        bp = bheadp;
  1816. X        while (bp != NULL) {
  1817. X                if ((bp->b_flag&BFINVS)==0 && (bp->b_flag&BFCHG)!=0)
  1818. X                        return (TRUE);
  1819. X                bp = bp->b_bufp;
  1820. X        }
  1821. X        return (FALSE);
  1822. X}
  1823. X
  1824. X/*
  1825. X * Find a buffer, by name. Return a pointer
  1826. X * to the BUFFER structure associated with it.
  1827. X * If the buffer is not found
  1828. X * and the "cflag" is TRUE, create it. The "bflag" is
  1829. X * the settings for the flags in in buffer.
  1830. X */
  1831. XBUFFER  *
  1832. Xbfind(bname, cflag, bflag)
  1833. Xregister char   *bname;
  1834. X{
  1835. X        register BUFFER *bp;
  1836. X    register BUFFER *sb;    /* buffer to insert after */
  1837. X        register LINE   *lp;
  1838. X    char *malloc();
  1839. X
  1840. X        bp = bheadp;
  1841. X        while (bp != NULL) {
  1842. X                if (strcmp(bname, bp->b_bname) == 0)
  1843. X                        return (bp);
  1844. X                bp = bp->b_bufp;
  1845. X        }
  1846. X        if (cflag != FALSE) {
  1847. X                if ((bp=(BUFFER *)malloc(sizeof(BUFFER))) == NULL)
  1848. X                        return (NULL);
  1849. X                if ((lp=lalloc(0)) == NULL) {
  1850. X                        free((char *) bp);
  1851. X                        return (NULL);
  1852. X                }
  1853. X        /* find the place in the list to insert this buffer */
  1854. X        if (bheadp == NULL || strcmp(bheadp->b_bname, bname) > 0) {
  1855. X            /* insert at the beginning */
  1856. X                    bp->b_bufp = bheadp;
  1857. X                    bheadp = bp;
  1858. X            } else {
  1859. X            sb = bheadp;
  1860. X            while (sb->b_bufp != NULL) {
  1861. X                if (strcmp(sb->b_bufp->b_bname, bname) > 0)
  1862. X                    break;
  1863. X                sb = sb->b_bufp;
  1864. X            }
  1865. X
  1866. X            /* and insert it */
  1867. X                   bp->b_bufp = sb->b_bufp;
  1868. X                sb->b_bufp = bp;
  1869. X               }
  1870. X
  1871. X        /* and set up the other buffer fields */
  1872. X        bp->b_active = TRUE;
  1873. X                bp->b_dotp  = lp;
  1874. X                bp->b_doto  = 0;
  1875. X                bp->b_markp = NULL;
  1876. X                bp->b_marko = 0;
  1877. X                bp->b_flag  = bflag;
  1878. X        bp->b_mode  = gmode;
  1879. X                bp->b_nwnd  = 0;
  1880. X                bp->b_linep = lp;
  1881. X                strcpy(bp->b_fname, "");
  1882. X                strcpy(bp->b_bname, bname);
  1883. X#if    CRYPT
  1884. X        bp->b_key[0] = 0;
  1885. X#endif
  1886. X                lp->l_fp = lp;
  1887. X                lp->l_bp = lp;
  1888. X        }
  1889. X        return (bp);
  1890. X}
  1891. X
  1892. X/*
  1893. X * This routine blows away all of the text
  1894. X * in a buffer. If the buffer is marked as changed
  1895. X * then we ask if it is ok to blow it away; this is
  1896. X * to save the user the grief of losing text. The
  1897. X * window chain is nearly always wrong if this gets
  1898. X * called; the caller must arrange for the updates
  1899. X * that are required. Return TRUE if everything
  1900. X * looks good.
  1901. X */
  1902. Xbclear(bp)
  1903. Xregister BUFFER *bp;
  1904. X{
  1905. X        register LINE   *lp;
  1906. X        register int    s;
  1907. X
  1908. X        if ((bp->b_flag&BFINVS) == 0            /* Not scratch buffer.  */
  1909. X        && (bp->b_flag&BFCHG) != 0              /* Something changed    */
  1910. X        && (s=mlyesno("Discard changes")) != TRUE)
  1911. X                return (s);
  1912. X        bp->b_flag  &= ~BFCHG;                  /* Not changed          */
  1913. X        while ((lp=lforw(bp->b_linep)) != bp->b_linep)
  1914. X                lfree(lp);
  1915. X        bp->b_dotp  = bp->b_linep;              /* Fix "."              */
  1916. X        bp->b_doto  = 0;
  1917. X        bp->b_markp = NULL;                     /* Invalidate "mark"    */
  1918. X        bp->b_marko = 0;
  1919. X        return (TRUE);
  1920. X}
  1921. X
  1922. Xunmark(f, n)    /* unmark the current buffers change flag */
  1923. X
  1924. Xint f, n;    /* unused command arguments */
  1925. X
  1926. X{
  1927. X    curbp->b_flag &= ~BFCHG;
  1928. X    curwp->w_flag |= WFMODE;
  1929. X    return(TRUE);
  1930. X}
  1931. E!O!F
  1932. newsize=`wc -c < buffer.c`
  1933. if [ $newsize -ne 16060 ]
  1934. then echo "File buffer.c was $newsize bytes, 16060 expected"
  1935. fi
  1936. echo 'x - crypt.c (text)'
  1937. sed << 'E!O!F' 's/^X//' > crypt.c
  1938. X/*    Crypt:    Encryption routines for MicroEMACS
  1939. X        written by Dana Hoggatt and Daniel Lawrence
  1940. X*/
  1941. X
  1942. X#include    <stdio.h>
  1943. X#include    "estruct.h"
  1944. X#include    "edef.h"
  1945. X
  1946. X#if    CRYPT
  1947. Xsetkey(f, n)    /* reset encryption key of current buffer */
  1948. X
  1949. Xint f;        /* default flag */
  1950. Xint n;        /* numeric argument */
  1951. X
  1952. X{
  1953. X    register int status;    /* return status */
  1954. X    int odisinp;        /* original vlaue of disinp */
  1955. X    char key[NPAT];        /* new encryption string */
  1956. X
  1957. X    /* turn command input echo off */
  1958. X    odisinp = disinp;
  1959. X    disinp = FALSE;
  1960. X
  1961. X    /* get the string to use as an encrytion string */
  1962. X    status = mlreply("Encryption String: ", key, NPAT - 1);
  1963. X    disinp = odisinp;
  1964. X        if (status != TRUE)
  1965. X                return(status);
  1966. X
  1967. X    /* and encrypt it */
  1968. X    crypt((char *)NULL, 0);
  1969. X    crypt(key, strlen(key));
  1970. X
  1971. X    /* and save it off */
  1972. X    strcpy(curbp->b_key, key);
  1973. X    mlwrite(" ");        /* clear it off the bottom line */
  1974. X    return(TRUE);
  1975. X}
  1976. X
  1977. X/**********
  1978. X *
  1979. X *    crypt - in place encryption/decryption of a buffer
  1980. X *
  1981. X *    (C) Copyright 1986, Dana L. Hoggatt
  1982. X *    1216, Beck Lane, Lafayette, IN
  1983. X *
  1984. X *    When consulting directly with the author of this routine, 
  1985. X *    please refer to this routine as the "DLH-POLY-86-B CIPHER".  
  1986. X *
  1987. X *    This routine was written for Dan Lawrence, for use in V3.8 of
  1988. X *    MicroEMACS, a public domain text/program editor.  
  1989. X *
  1990. X *    I kept the following goals in mind when preparing this function:
  1991. X *
  1992. X *        1.    All printable characters were to be encrypted back
  1993. X *        into the printable range, control characters and
  1994. X *        high-bit characters were to remain unaffected.  this
  1995. X *        way, encrypted would still be just as cheap to 
  1996. X *        transmit down a 7-bit data path as they were before.
  1997. X *
  1998. X *        2.    The encryption had to be portable.  The encrypted 
  1999. X *        file from one computer should be able to be decrypted 
  2000. X *        on another computer.
  2001. X *
  2002. X *        3.    The encryption had to be inexpensive, both in terms
  2003. X *        of speed and space.
  2004. X *
  2005. X *        4.    The system needed to be secure against all but the
  2006. X *        most determined of attackers.
  2007. X *
  2008. X *    For encryption of a block of data, one calls crypt passing 
  2009. X *    a pointer to the data block and its length. The data block is 
  2010. X *    encrypted in place, that is, the encrypted output overwrites 
  2011. X *    the input.  Decryption is totally isomorphic, and is performed 
  2012. X *    in the same manner by the same routine.  
  2013. X *
  2014. X *    Before using this routine for encrypting data, you are expected 
  2015. X *    to specify an encryption key.  This key is an arbitrary string,
  2016. X *    to be supplied by the user.  To set the key takes two calls to 
  2017. X *    crypt().  First, you call 
  2018. X *
  2019. X *        crypt(NULL, vector)
  2020. X *
  2021. X *    This resets all internal control information.  Typically (and 
  2022. X *    specifically in the case on MICRO-emacs) you would use a "vector" 
  2023. X *    of 0.  Other values can be used to customize your editor to be 
  2024. X *    "incompatable" with the normally distributed version.  For 
  2025. X *    this purpose, the best results will be obtained by avoiding
  2026. X *    multiples of 95.
  2027. X *
  2028. X *    Then, you "encrypt" your password by calling 
  2029. X *
  2030. X *        crypt(pass, strlen(pass))
  2031. X *
  2032. X *    where "pass" is your password string.  Crypt() will destroy 
  2033. X *    the original copy of the password (it becomes encrypted), 
  2034. X *    which is good.  You do not want someone on a multiuser system 
  2035. X *    to peruse your memory space and bump into your password.  
  2036. X *    Still, it is a better idea to erase the password buffer to 
  2037. X *    defeat memory perusal by a more technical snooper.  
  2038. X *
  2039. X *    For the interest of cryptologists, at the heart of this 
  2040. X *    function is a Beaufort Cipher.  The cipher alphabet is the 
  2041. X *    range of printable characters (' ' to '~'), all "control" 
  2042. X *    and "high-bit" characters are left unaltered.
  2043. X *
  2044. X *    The key is a variant autokey, derived from a wieghted sum 
  2045. X *    of all the previous clear text and cipher text.  A counter 
  2046. X *    is used as salt to obiterate any simple cyclic behavior 
  2047. X *    from the clear text, and key feedback is used to assure 
  2048. X *    that the entire message is based on the original key, 
  2049. X *    preventing attacks on the last part of the message as if 
  2050. X *    it were a pure autokey system.
  2051. X *
  2052. X *    Overall security of encrypted data depends upon three 
  2053. X *    factors:  the fundamental cryptographic system must be 
  2054. X *    difficult to compromise; exhaustive searching of the key 
  2055. X *    space must be computationally expensive; keys and plaintext 
  2056. X *    must remain out of sight.  This system satisfies this set
  2057. X *    of conditions to within the degree desired for MicroEMACS.
  2058. X *
  2059. X *    Though direct methods of attack (against systems such as 
  2060. X *    this) do exist, they are not well known and will consume 
  2061. X *    considerable amounts of computing time.  An exhaustive
  2062. X *    search requires over a billion investigations, on average.
  2063. X *
  2064. X *    The choice, entry, storage, manipulation, alteration, 
  2065. X *    protection and security of the keys themselves are the 
  2066. X *    responsiblity of the user.  
  2067. X *
  2068. X **********/
  2069. X
  2070. Xcrypt(bptr, len)
  2071. Xregister char *bptr;    /* buffer of characters to be encrypted */
  2072. Xregister unsigned len;    /* number of characters in the buffer */
  2073. X{
  2074. X    register int cc;    /* current character being considered */
  2075. X
  2076. X    static long key = 0;    /* 29 bit encipherment key */
  2077. X    static int salt = 0;    /* salt to spice up key with */
  2078. X
  2079. X    if (!bptr) {        /* is there anything here to encrypt? */
  2080. X        key = len;    /* set the new key */
  2081. X        salt = len;    /* set the new salt */
  2082. X        return;
  2083. X    }
  2084. X    while (len--) {        /* for every character in the buffer */
  2085. X
  2086. X        cc = *bptr;    /* get a character out of the buffer */
  2087. X
  2088. X        /* only encipher printable characters */
  2089. X        if ((cc >= ' ') && (cc <= '~')) {
  2090. X
  2091. X/**  If the upper bit (bit 29) is set, feed it back into the key.  This 
  2092. X    assures us that the starting key affects the entire message.  **/
  2093. X
  2094. X            key &= 0x1FFFFFFFL;    /* strip off overflow */
  2095. X            if (key & 0x10000000L) {
  2096. X                key ^= 0x0040A001L;    /* feedback */
  2097. X            }
  2098. X
  2099. X/**  Down-bias the character, perform a Beaufort encipherment, and 
  2100. X    up-bias the character again.  We want key to be positive 
  2101. X    so that the left shift here will be more portable and the 
  2102. X    mod95() faster   **/
  2103. X
  2104. X            cc = mod95((int)(key % 95) - (cc - ' ')) + ' ';
  2105. X
  2106. X/**  the salt will spice up the key a little bit, helping to obscure 
  2107. X    any patterns in the clear text, particularly when all the 
  2108. X    characters (or long sequences of them) are the same.  We do 
  2109. X    not want the salt to go negative, or it will affect the key 
  2110. X    too radically.  It is always a good idea to chop off cyclics 
  2111. X    to prime values.  **/
  2112. X
  2113. X            if (++salt >= 20857) {    /* prime modulus */
  2114. X                salt = 0;
  2115. X            }
  2116. X
  2117. X/**  our autokey (a special case of the running key) is being 
  2118. X    generated by a wieghted checksum of clear text, cipher 
  2119. X    text, and salt.   **/
  2120. X
  2121. X            key = key + key + cc + *bptr + salt;
  2122. X        }
  2123. X        *bptr++ = cc;    /* put character back into buffer */
  2124. X    }
  2125. X    return;
  2126. X}
  2127. X
  2128. Xstatic int mod95(val)
  2129. X
  2130. Xregister int val;
  2131. X
  2132. X{
  2133. X    /*  The mathematical MOD does not match the computer MOD  */
  2134. X
  2135. X    /*  Yes, what I do here may look strange, but it gets the
  2136. X        job done, and portably at that.  */
  2137. X
  2138. X    while (val >= 9500)
  2139. X        val -= 9500;
  2140. X    while (val >= 950)
  2141. X        val -= 950;
  2142. X    while (val >= 95)
  2143. X        val -= 95;
  2144. X    while (val < 0)
  2145. X        val += 95;
  2146. X    return (val);
  2147. X}
  2148. X#else
  2149. Xnocrypt()
  2150. X{
  2151. X}
  2152. X#endif
  2153. E!O!F
  2154. newsize=`wc -c < crypt.c`
  2155. if [ $newsize -ne 6981 ]
  2156. then echo "File crypt.c was $newsize bytes, 6981 expected"
  2157. fi
  2158. echo 'x - dg10.c (text)'
  2159. sed << 'E!O!F' 's/^X//' > dg10.c
  2160. X/*
  2161. X * The routines in this file provide support for the Data General Model 10
  2162. X * Microcomputer.
  2163. X */
  2164. X
  2165. X#define    termdef    1            /* don't define "term" external */
  2166. X
  2167. X#include        <stdio.h>
  2168. X#include    "estruct.h"
  2169. X#include        "edef.h"
  2170. X
  2171. X#if     DG10
  2172. X
  2173. X#define NROW    24                      /* Screen size.                 */
  2174. X#define NCOL    80                      /* Edit if you want to.         */
  2175. X#define    NPAUSE    100            /* # times thru update to pause */
  2176. X#define    MARGIN    8            /* size of minimim margin and    */
  2177. X#define    SCRSIZ    64            /* scroll size for extended lines */
  2178. X#define BEL     0x07                    /* BEL character.               */
  2179. X#define ESC     30                      /* DG10 ESC character.          */
  2180. X
  2181. Xextern  int     ttopen();               /* Forward references.          */
  2182. Xextern  int     ttgetc();
  2183. Xextern  int     ttputc();
  2184. Xextern  int     ttflush();
  2185. Xextern  int     ttclose();
  2186. Xextern    int    dg10kopen();
  2187. Xextern    int    dg10kclose();
  2188. Xextern  int     dg10move();
  2189. Xextern  int     dg10eeol();
  2190. Xextern  int     dg10eeop();
  2191. Xextern  int     dg10beep();
  2192. Xextern  int     dg10open();
  2193. Xextern    int    dg10rev();
  2194. Xextern    int    dg10close();
  2195. Xextern    int    dg10cres();
  2196. X
  2197. X#if    COLOR
  2198. Xextern    int    dg10fcol();
  2199. Xextern    int    dg10bcol();
  2200. X
  2201. Xint    cfcolor = -1;        /* current forground color */
  2202. Xint    cbcolor = -1;        /* current background color */
  2203. Xint    ctrans[] = {        /* emacs -> DG10 color translation table */
  2204. X    0, 4, 2, 6, 1, 5, 3, 7};
  2205. X#endif
  2206. X
  2207. X/*
  2208. X * Standard terminal interface dispatch table. Most of the fields point into
  2209. X * "termio" code.
  2210. X */
  2211. XTERM    term    = {
  2212. X    NROW-1,
  2213. X        NROW-1,
  2214. X        NCOL,
  2215. X        NCOL,
  2216. X    MARGIN,
  2217. X    SCRSIZ,
  2218. X    NPAUSE,
  2219. X        dg10open,
  2220. X        dg10close,
  2221. X    dg10kopen,
  2222. X    dg10kclose,
  2223. X        ttgetc,
  2224. X        ttputc,
  2225. X        ttflush,
  2226. X        dg10move,
  2227. X        dg10eeol,
  2228. X        dg10eeop,
  2229. X        dg10beep,
  2230. X    dg10rev,
  2231. X    dg10cres
  2232. X#if    COLOR
  2233. X    , dg10fcol,
  2234. X    dg10bcol
  2235. X#endif
  2236. X};
  2237. X
  2238. X#if    COLOR
  2239. Xdg10fcol(color)        /* set the current output color */
  2240. X
  2241. Xint color;    /* color to set */
  2242. X
  2243. X{
  2244. X    if (color == cfcolor)
  2245. X        return;
  2246. X    ttputc(ESC);
  2247. X    ttputc(0101);
  2248. X    ttputc(ctrans[color]);
  2249. X    cfcolor = color;
  2250. X}
  2251. X
  2252. Xdg10bcol(color)        /* set the current background color */
  2253. X
  2254. Xint color;    /* color to set */
  2255. X
  2256. X{
  2257. X    if (color == cbcolor)
  2258. X        return;
  2259. X    ttputc(ESC);
  2260. X    ttputc(0102);
  2261. X    ttputc(ctrans[color]);
  2262. X        cbcolor = color;
  2263. X}
  2264. X#endif
  2265. X
  2266. Xdg10move(row, col)
  2267. X{
  2268. X    ttputc(16);
  2269. X        ttputc(col);
  2270. X    ttputc(row);
  2271. X}
  2272. X
  2273. Xdg10eeol()
  2274. X{
  2275. X        ttputc(11);
  2276. X}
  2277. X
  2278. Xdg10eeop()
  2279. X{
  2280. X#if    COLOR
  2281. X    dg10fcol(gfcolor);
  2282. X    dg10bcol(gbcolor);
  2283. X#endif
  2284. X        ttputc(ESC);
  2285. X        ttputc(0106);
  2286. X        ttputc(0106);
  2287. X}
  2288. X
  2289. Xdg10rev(state)        /* change reverse video state */
  2290. X
  2291. Xint state;    /* TRUE = reverse, FALSE = normal */
  2292. X
  2293. X{
  2294. X#if    COLOR
  2295. X    if (state == TRUE) {
  2296. X        dg10fcol(0);
  2297. X        dg10bcol(7);
  2298. X    }
  2299. X#else
  2300. X    ttputc(ESC);
  2301. X    ttputc(state ? 0104: 0105);
  2302. X#endif
  2303. X}
  2304. X
  2305. Xdg10cres()    /* change screen resolution */
  2306. X
  2307. X{
  2308. X    return(TRUE);
  2309. X}
  2310. X
  2311. Xspal()        /* change palette string */
  2312. X
  2313. X{
  2314. X    /*    Does nothing here    */
  2315. X}
  2316. X
  2317. Xdg10beep()
  2318. X{
  2319. X        ttputc(BEL);
  2320. X        ttflush();
  2321. X}
  2322. X
  2323. Xdg10open()
  2324. X{
  2325. X    strcpy(sres, "NORMAL");
  2326. X    revexist = TRUE;
  2327. X        ttopen();
  2328. X}
  2329. X
  2330. Xdg10close()
  2331. X
  2332. X{
  2333. X#if    COLOR
  2334. X    dg10fcol(7);
  2335. X    dg10bcol(0);
  2336. X#endif
  2337. X    ttclose();
  2338. X}
  2339. X
  2340. Xdg10kopen()
  2341. X
  2342. X{
  2343. X}
  2344. X
  2345. Xdg10kclose()
  2346. X
  2347. X{
  2348. X}
  2349. X
  2350. X#if    FLABEL
  2351. Xfnclabel(f, n)        /* label a function key */
  2352. X
  2353. Xint f,n;    /* default flag, numeric argument [unused] */
  2354. X
  2355. X{
  2356. X    /* on machines with no function keys...don't bother */
  2357. X    return(TRUE);
  2358. X}
  2359. X#endif
  2360. X#else
  2361. Xdg10hello()
  2362. X{
  2363. X}
  2364. X#endif
  2365. E!O!F
  2366. newsize=`wc -c < dg10.c`
  2367. if [ $newsize -ne 3333 ]
  2368. then echo "File dg10.c was $newsize bytes, 3333 expected"
  2369. fi
  2370.     bill davidsen        (wedu@ge-crd.arpa)
  2371.   {chinet | philabs | sesimo}!steinmetz!crdos1!davidsen
  2372. "Stupidity, like virtue, is its own reward" -me
  2373.  
  2374.  
  2375.