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

  1. Article 78 of comp.sources.misc:
  2. Path: tut!osu-cis!cbosgd!mandrill!hal!ncoast!allbery
  3. From: nwd@j.cc.purdue.edu (Daniel Lawrence)
  4. Newsgroups: comp.sources.misc
  5. Subject: MicroEmacs 3.9 (Part 2 of 16)
  6. Message-ID: <5649@ncoast.UUCP>
  7. Date: 14 Nov 87 21:06:32 GMT
  8. Sender: allbery@ncoast.UUCP
  9. Lines: 974
  10. Approved: allbery@ncoast.UUCP
  11. X-Archive: comp.sources.misc/microemacs-3.9/1
  12.  
  13. # This is a shar archive.
  14. # Remove everything above this line.
  15. # Run the file through sh, not csh.
  16. # (type `sh mes.2')
  17. # If you do not see the message
  18. #    `mes.2 completed!'
  19. # then the file was incomplete.
  20. echo extracting - buffer.c
  21. sed 's/^X//' > buffer.c << 'FRIDAY_NIGHT'
  22. X/*
  23. X * Buffer management.
  24. X * Some of the functions are internal,
  25. X * and some are actually attached to user
  26. X * keys. Like everyone else, they set hints
  27. X * for the display system.
  28. X */
  29. X#include        <stdio.h>
  30. X#include    "estruct.h"
  31. X#include        "edef.h"
  32. X
  33. X/*
  34. X * Attach a buffer to a window. The
  35. X * values of dot and mark come from the buffer
  36. X * if the use count is 0. Otherwise, they come
  37. X * from some other window.
  38. X */
  39. Xusebuffer(f, n)
  40. X{
  41. X        register BUFFER *bp;
  42. X        register int    s;
  43. X        char            bufn[NBUFN];
  44. X
  45. X        if ((s=mlreply("Use buffer: ", bufn, NBUFN)) != TRUE)
  46. X                return (s);
  47. X        if ((bp=bfind(bufn, TRUE, 0)) == NULL)
  48. X                return (FALSE);
  49. X    return(swbuffer(bp));
  50. X}
  51. X
  52. Xnextbuffer(f, n)    /* switch to the next buffer in the buffer list */
  53. X
  54. Xint f, n;    /* default flag, numeric argument */
  55. X{
  56. X    register BUFFER *bp;    /* eligable buffer to switch to*/
  57. X    register BUFFER *bbp;    /* eligable buffer to switch to*/
  58. X
  59. X    /* make sure the arg is legit */
  60. X    if (f == FALSE)
  61. X        n = 1;
  62. X    if (n < 1)
  63. X        return(FALSE);
  64. X
  65. X    bbp = curbp;
  66. X    while (n-- > 0) {
  67. X        /* advance to the next buffer */
  68. X        bp = bbp->b_bufp;
  69. X
  70. X        /* cycle through the buffers to find an eligable one */
  71. X        while (bp == NULL || bp->b_flag & BFINVS) {
  72. X            if (bp == NULL)
  73. X                bp = bheadp;
  74. X            else
  75. X                bp = bp->b_bufp;
  76. X
  77. X            /* don't get caught in an infinite loop! */
  78. X            if (bp == bbp)
  79. X                return(FALSE);
  80. X
  81. X        }        
  82. X
  83. X        bbp = bp;
  84. X    }
  85. X
  86. X    return(swbuffer(bp));
  87. X}
  88. X
  89. Xswbuffer(bp)    /* make buffer BP current */
  90. X
  91. XBUFFER *bp;
  92. X
  93. X{
  94. X        register WINDOW *wp;
  95. X
  96. X        if (--curbp->b_nwnd == 0) {             /* Last use.            */
  97. X                curbp->b_dotp  = curwp->w_dotp;
  98. X                curbp->b_doto  = curwp->w_doto;
  99. X                curbp->b_markp = curwp->w_markp;
  100. X                curbp->b_marko = curwp->w_marko;
  101. X        }
  102. X        curbp = bp;                             /* Switch.              */
  103. X    if (curbp->b_active != TRUE) {        /* buffer not active yet*/
  104. X        /* read it in and activate it */
  105. X        readin(curbp->b_fname, TRUE);
  106. X        curbp->b_dotp = lforw(curbp->b_linep);
  107. X        curbp->b_doto = 0;
  108. X        curbp->b_active = TRUE;
  109. X    }
  110. X        curwp->w_bufp  = bp;
  111. X        curwp->w_linep = bp->b_linep;           /* For macros, ignored. */
  112. X        curwp->w_flag |= WFMODE|WFFORCE|WFHARD; /* Quite nasty.         */
  113. X        if (bp->b_nwnd++ == 0) {                /* First use.           */
  114. X                curwp->w_dotp  = bp->b_dotp;
  115. X                curwp->w_doto  = bp->b_doto;
  116. X                curwp->w_markp = bp->b_markp;
  117. X                curwp->w_marko = bp->b_marko;
  118. X                return (TRUE);
  119. X        }
  120. X        wp = wheadp;                            /* Look for old.        */
  121. X        while (wp != NULL) {
  122. X                if (wp!=curwp && wp->w_bufp==bp) {
  123. X                        curwp->w_dotp  = wp->w_dotp;
  124. X                        curwp->w_doto  = wp->w_doto;
  125. X                        curwp->w_markp = wp->w_markp;
  126. X                        curwp->w_marko = wp->w_marko;
  127. X                        break;
  128. X                }
  129. X                wp = wp->w_wndp;
  130. X        }
  131. X        return (TRUE);
  132. X}
  133. X
  134. X/*
  135. X * Dispose of a buffer, by name.
  136. X * Ask for the name. Look it up (don't get too
  137. X * upset if it isn't there at all!). Get quite upset
  138. X * if the buffer is being displayed. Clear the buffer (ask
  139. X * if the buffer has been changed). Then free the header
  140. X * line and the buffer header. Bound to "C-X K".
  141. X */
  142. Xkillbuffer(f, n)
  143. X
  144. X{
  145. X    register BUFFER *bp;
  146. X        register int    s;
  147. X        char bufn[NBUFN];
  148. X
  149. X        if ((s=mlreply("Kill buffer: ", bufn, NBUFN)) != TRUE)
  150. X                return(s);
  151. X        if ((bp=bfind(bufn, FALSE, 0)) == NULL) /* Easy if unknown.     */
  152. X                return (TRUE);
  153. X    if(bp->b_flag & BFINVS)        /* Deal with special buffers    */
  154. X            return (TRUE);        /* by doing nothing.    */
  155. X    return(zotbuf(bp));
  156. X}
  157. X
  158. Xzotbuf(bp)    /* kill the buffer pointed to by bp */
  159. X
  160. Xregister BUFFER *bp;
  161. X
  162. X{
  163. X        register BUFFER *bp1;
  164. X        register BUFFER *bp2;
  165. X        register int    s;
  166. X
  167. X        if (bp->b_nwnd != 0) {                  /* Error if on screen.  */
  168. X                mlwrite("Buffer is being displayed");
  169. X                return (FALSE);
  170. X        }
  171. X        if ((s=bclear(bp)) != TRUE)             /* Blow text away.      */
  172. X                return (s);
  173. X        free((char *) bp->b_linep);             /* Release header line. */
  174. X        bp1 = NULL;                             /* Find the header.     */
  175. X        bp2 = bheadp;
  176. X        while (bp2 != bp) {
  177. X                bp1 = bp2;
  178. X                bp2 = bp2->b_bufp;
  179. X        }
  180. X        bp2 = bp2->b_bufp;                      /* Next one in chain.   */
  181. X        if (bp1 == NULL)                        /* Unlink it.           */
  182. X                bheadp = bp2;
  183. X        else
  184. X                bp1->b_bufp = bp2;
  185. X        free((char *) bp);                      /* Release buffer block */
  186. X        return (TRUE);
  187. X}
  188. X
  189. Xnamebuffer(f,n)        /*    Rename the current buffer    */
  190. X
  191. Xint f, n;        /* default Flag & Numeric arg */
  192. X
  193. X{
  194. X    register BUFFER *bp;    /* pointer to scan through all buffers */
  195. X    char bufn[NBUFN];    /* buffer to hold buffer name */
  196. X
  197. X    /* prompt for and get the new buffer name */
  198. Xask:    if (mlreply("Change buffer name to: ", bufn, NBUFN) != TRUE)
  199. X        return(FALSE);
  200. X
  201. X    /* and check for duplicates */
  202. X    bp = bheadp;
  203. X    while (bp != NULL) {
  204. X        if (bp != curbp) {
  205. X            /* if the names the same */
  206. X            if (strcmp(bufn, bp->b_bname) == 0)
  207. X                goto ask;  /* try again */
  208. X        }
  209. X        bp = bp->b_bufp;    /* onward */
  210. X    }
  211. X
  212. X    strcpy(curbp->b_bname, bufn);    /* copy buffer name to structure */
  213. X    curwp->w_flag |= WFMODE;    /* make mode line replot */
  214. X    mlerase();
  215. X    return(TRUE);
  216. X}
  217. X
  218. X/*
  219. X    List all of the active buffers.  First update the special
  220. X    buffer that holds the list.  Next make sure at least 1
  221. X    window is displaying the buffer list, splitting the screen
  222. X    if this is what it takes.  Lastly, repaint all of the
  223. X    windows that are displaying the list.  Bound to "C-X C-B". 
  224. X    A numeric argument forces it to list invisable buffers as
  225. X    well.
  226. X*/
  227. X
  228. Xlistbuffers(f, n)
  229. X{
  230. X        register WINDOW *wp;
  231. X        register BUFFER *bp;
  232. X        register int    s;
  233. X
  234. X        if ((s=makelist(f)) != TRUE)
  235. X                return (s);
  236. X        if (blistp->b_nwnd == 0) {              /* Not on screen yet.   */
  237. X                if ((wp=wpopup()) == NULL)
  238. X                        return (FALSE);
  239. X                bp = wp->w_bufp;
  240. X                if (--bp->b_nwnd == 0) {
  241. X                        bp->b_dotp  = wp->w_dotp;
  242. X                        bp->b_doto  = wp->w_doto;
  243. X                        bp->b_markp = wp->w_markp;
  244. X                        bp->b_marko = wp->w_marko;
  245. X                }
  246. X                wp->w_bufp  = blistp;
  247. X                ++blistp->b_nwnd;
  248. X        }
  249. X        wp = wheadp;
  250. X        while (wp != NULL) {
  251. X                if (wp->w_bufp == blistp) {
  252. X                        wp->w_linep = lforw(blistp->b_linep);
  253. X                        wp->w_dotp  = lforw(blistp->b_linep);
  254. X                        wp->w_doto  = 0;
  255. X                        wp->w_markp = NULL;
  256. X                        wp->w_marko = 0;
  257. X                        wp->w_flag |= WFMODE|WFHARD;
  258. X                }
  259. X                wp = wp->w_wndp;
  260. X        }
  261. X        return (TRUE);
  262. X}
  263. X
  264. X/*
  265. X * This routine rebuilds the
  266. X * text in the special secret buffer
  267. X * that holds the buffer list. It is called
  268. X * by the list buffers command. Return TRUE
  269. X * if everything works. Return FALSE if there
  270. X * is an error (if there is no memory). Iflag
  271. X * indecates weather to list hidden buffers.
  272. X */
  273. Xmakelist(iflag)
  274. X
  275. Xint iflag;    /* list hidden buffer flag */
  276. X
  277. X{
  278. X        register char   *cp1;
  279. X        register char   *cp2;
  280. X        register int    c;
  281. X        register BUFFER *bp;
  282. X        register LINE   *lp;
  283. X        register int    s;
  284. X    register int    i;
  285. X        long nbytes;        /* # of bytes in current buffer */
  286. X        char b[7+1];
  287. X        char line[128];
  288. X
  289. X        blistp->b_flag &= ~BFCHG;               /* Don't complain!      */
  290. X        if ((s=bclear(blistp)) != TRUE)         /* Blow old text away   */
  291. X                return (s);
  292. X        strcpy(blistp->b_fname, "");
  293. X        if (addline("ACT MODES        Size Buffer        File") == FALSE
  294. X        ||  addline("--- -----        ---- ------        ----") == FALSE)
  295. X                return (FALSE);
  296. X        bp = bheadp;                            /* For all buffers      */
  297. X
  298. X    /* build line to report global mode settings */
  299. X    cp1 = &line[0];
  300. X    *cp1++ = ' ';
  301. X    *cp1++ = ' ';
  302. X    *cp1++ = ' ';
  303. X    *cp1++ = ' ';
  304. X
  305. X    /* output the mode codes */
  306. X    for (i = 0; i < NUMMODES; i++)
  307. X        if (gmode & (1 << i))
  308. X            *cp1++ = modecode[i];
  309. X        else
  310. X            *cp1++ = '.';
  311. X    strcpy(cp1, "         Global Modes");
  312. X    if (addline(line) == FALSE)
  313. X        return(FALSE);
  314. X
  315. X    /* output the list of buffers */
  316. X        while (bp != NULL) {
  317. X        /* skip invisable buffers if iflag is false */
  318. X                if (((bp->b_flag&BFINVS) != 0) && (iflag != TRUE)) {
  319. X                        bp = bp->b_bufp;
  320. X                        continue;
  321. X                }
  322. X                cp1 = &line[0];                 /* Start at left edge   */
  323. X
  324. X        /* output status of ACTIVE flag (has the file been read in? */
  325. X                if (bp->b_active == TRUE)    /* "@" if activated       */
  326. X                        *cp1++ = '@';
  327. X                else
  328. X                        *cp1++ = ' ';
  329. X
  330. X        /* output status of changed flag */
  331. X                if ((bp->b_flag&BFCHG) != 0)    /* "*" if changed       */
  332. X                        *cp1++ = '*';
  333. X                else
  334. X                        *cp1++ = ' ';
  335. X
  336. X        /* report if the file is truncated */
  337. X                if ((bp->b_flag&BFTRUNC) != 0)
  338. X                        *cp1++ = '#';
  339. X                else
  340. X                        *cp1++ = ' ';
  341. X
  342. X                *cp1++ = ' ';    /* space */
  343. X
  344. X        /* output the mode codes */
  345. X        for (i = 0; i < NUMMODES; i++) {
  346. X            if (bp->b_mode & (1 << i))
  347. X                *cp1++ = modecode[i];
  348. X            else
  349. X                *cp1++ = '.';
  350. X        }
  351. X                *cp1++ = ' ';                   /* Gap.                 */
  352. X                nbytes = 0L;                    /* Count bytes in buf.  */
  353. X                lp = lforw(bp->b_linep);
  354. X                while (lp != bp->b_linep) {
  355. X                        nbytes += (long)llength(lp)+1L;
  356. X                        lp = lforw(lp);
  357. X                }
  358. X                ltoa(b, 7, nbytes);             /* 6 digit buffer size. */
  359. X                cp2 = &b[0];
  360. X                while ((c = *cp2++) != 0)
  361. X                        *cp1++ = c;
  362. X                *cp1++ = ' ';                   /* Gap.                 */
  363. X                cp2 = &bp->b_bname[0];          /* Buffer name          */
  364. X                while ((c = *cp2++) != 0)
  365. X                        *cp1++ = c;
  366. X                cp2 = &bp->b_fname[0];          /* File name            */
  367. X                if (*cp2 != 0) {
  368. X                        while (cp1 < &line[3+1+5+1+6+4+NBUFN])
  369. X                                *cp1++ = ' ';
  370. X                        while ((c = *cp2++) != 0) {
  371. X                                if (cp1 < &line[128-1])
  372. X                                        *cp1++ = c;
  373. X                        }
  374. X                }
  375. X                *cp1 = 0;                       /* Add to the buffer.   */
  376. X                if (addline(line) == FALSE)
  377. X                        return (FALSE);
  378. X                bp = bp->b_bufp;
  379. X        }
  380. X        return (TRUE);                          /* All done             */
  381. X}
  382. X
  383. Xltoa(buf, width, num)
  384. X
  385. Xchar   buf[];
  386. Xint    width;
  387. Xlong   num;
  388. X
  389. X{
  390. X        buf[width] = 0;                         /* End of string.       */
  391. X        while (num >= 10) {                     /* Conditional digits.  */
  392. X                buf[--width] = (int)(num%10L) + '0';
  393. X                num /= 10L;
  394. X        }
  395. X        buf[--width] = (int)num + '0';          /* Always 1 digit.      */
  396. X        while (width != 0)                      /* Pad with blanks.     */
  397. X                buf[--width] = ' ';
  398. X}
  399. X
  400. X/*
  401. X * The argument "text" points to
  402. X * a string. Append this line to the
  403. X * buffer list buffer. Handcraft the EOL
  404. X * on the end. Return TRUE if it worked and
  405. X * FALSE if you ran out of room.
  406. X */
  407. Xaddline(text)
  408. Xchar    *text;
  409. X{
  410. X        register LINE   *lp;
  411. X        register int    i;
  412. X        register int    ntext;
  413. X
  414. X        ntext = strlen(text);
  415. X        if ((lp=lalloc(ntext)) == NULL)
  416. X                return (FALSE);
  417. X        for (i=0; i<ntext; ++i)
  418. X                lputc(lp, i, text[i]);
  419. X        blistp->b_linep->l_bp->l_fp = lp;       /* Hook onto the end    */
  420. X        lp->l_bp = blistp->b_linep->l_bp;
  421. X        blistp->b_linep->l_bp = lp;
  422. X        lp->l_fp = blistp->b_linep;
  423. X        if (blistp->b_dotp == blistp->b_linep)  /* If "." is at the end */
  424. X                blistp->b_dotp = lp;            /* move it to new line  */
  425. X        return (TRUE);
  426. X}
  427. X
  428. X/*
  429. X * Look through the list of
  430. X * buffers. Return TRUE if there
  431. X * are any changed buffers. Buffers
  432. X * that hold magic internal stuff are
  433. X * not considered; who cares if the
  434. X * list of buffer names is hacked.
  435. X * Return FALSE if no buffers
  436. X * have been changed.
  437. X */
  438. Xanycb()
  439. X{
  440. X        register BUFFER *bp;
  441. X
  442. X        bp = bheadp;
  443. X        while (bp != NULL) {
  444. X                if ((bp->b_flag&BFINVS)==0 && (bp->b_flag&BFCHG)!=0)
  445. X                        return (TRUE);
  446. X                bp = bp->b_bufp;
  447. X        }
  448. X        return (FALSE);
  449. X}
  450. X
  451. X/*
  452. X * Find a buffer, by name. Return a pointer
  453. X * to the BUFFER structure associated with it.
  454. X * If the buffer is not found
  455. X * and the "cflag" is TRUE, create it. The "bflag" is
  456. X * the settings for the flags in in buffer.
  457. X */
  458. XBUFFER  *
  459. Xbfind(bname, cflag, bflag)
  460. Xregister char   *bname;
  461. X{
  462. X        register BUFFER *bp;
  463. X    register BUFFER *sb;    /* buffer to insert after */
  464. X        register LINE   *lp;
  465. X    char *malloc();
  466. X
  467. X        bp = bheadp;
  468. X        while (bp != NULL) {
  469. X                if (strcmp(bname, bp->b_bname) == 0)
  470. X                        return (bp);
  471. X                bp = bp->b_bufp;
  472. X        }
  473. X        if (cflag != FALSE) {
  474. X                if ((bp=(BUFFER *)malloc(sizeof(BUFFER))) == NULL)
  475. X                        return (NULL);
  476. X                if ((lp=lalloc(0)) == NULL) {
  477. X                        free((char *) bp);
  478. X                        return (NULL);
  479. X                }
  480. X        /* find the place in the list to insert this buffer */
  481. X        if (bheadp == NULL || strcmp(bheadp->b_bname, bname) > 0) {
  482. X            /* insert at the beginning */
  483. X                    bp->b_bufp = bheadp;
  484. X                    bheadp = bp;
  485. X            } else {
  486. X            sb = bheadp;
  487. X            while (sb->b_bufp != NULL) {
  488. X                if (strcmp(sb->b_bufp->b_bname, bname) > 0)
  489. X                    break;
  490. X                sb = sb->b_bufp;
  491. X            }
  492. X
  493. X            /* and insert it */
  494. X                   bp->b_bufp = sb->b_bufp;
  495. X                sb->b_bufp = bp;
  496. X               }
  497. X
  498. X        /* and set up the other buffer fields */
  499. X        bp->b_active = TRUE;
  500. X                bp->b_dotp  = lp;
  501. X                bp->b_doto  = 0;
  502. X                bp->b_markp = NULL;
  503. X                bp->b_marko = 0;
  504. X                bp->b_flag  = bflag;
  505. X        bp->b_mode  = gmode;
  506. X                bp->b_nwnd  = 0;
  507. X                bp->b_linep = lp;
  508. X                strcpy(bp->b_fname, "");
  509. X                strcpy(bp->b_bname, bname);
  510. X#if    CRYPT
  511. X        bp->b_key[0] = 0;
  512. X#endif
  513. X                lp->l_fp = lp;
  514. X                lp->l_bp = lp;
  515. X        }
  516. X        return (bp);
  517. X}
  518. X
  519. X/*
  520. X * This routine blows away all of the text
  521. X * in a buffer. If the buffer is marked as changed
  522. X * then we ask if it is ok to blow it away; this is
  523. X * to save the user the grief of losing text. The
  524. X * window chain is nearly always wrong if this gets
  525. X * called; the caller must arrange for the updates
  526. X * that are required. Return TRUE if everything
  527. X * looks good.
  528. X */
  529. Xbclear(bp)
  530. Xregister BUFFER *bp;
  531. X{
  532. X        register LINE   *lp;
  533. X        register int    s;
  534. X
  535. X        if ((bp->b_flag&BFINVS) == 0            /* Not scratch buffer.  */
  536. X        && (bp->b_flag&BFCHG) != 0              /* Something changed    */
  537. X        && (s=mlyesno("Discard changes")) != TRUE)
  538. X                return (s);
  539. X        bp->b_flag  &= ~BFCHG;                  /* Not changed          */
  540. X        while ((lp=lforw(bp->b_linep)) != bp->b_linep)
  541. X                lfree(lp);
  542. X        bp->b_dotp  = bp->b_linep;              /* Fix "."              */
  543. X        bp->b_doto  = 0;
  544. X        bp->b_markp = NULL;                     /* Invalidate "mark"    */
  545. X        bp->b_marko = 0;
  546. X        return (TRUE);
  547. X}
  548. X
  549. Xunmark(f, n)    /* unmark the current buffers change flag */
  550. X
  551. Xint f, n;    /* unused command arguments */
  552. X
  553. X{
  554. X    curbp->b_flag &= ~BFCHG;
  555. X    curwp->w_flag |= WFMODE;
  556. X    return(TRUE);
  557. X}
  558. FRIDAY_NIGHT
  559. echo extracting - crypt.c
  560. sed 's/^X//' > crypt.c << 'FRIDAY_NIGHT'
  561. X/*    Crypt:    Encryption routines for MicroEMACS
  562. X        written by Dana Hoggatt and Daniel Lawrence
  563. X*/
  564. X
  565. X#include    <stdio.h>
  566. X#include    "estruct.h"
  567. X#include    "edef.h"
  568. X
  569. X#if    CRYPT
  570. Xsetkey(f, n)    /* reset encryption key of current buffer */
  571. X
  572. Xint f;        /* default flag */
  573. Xint n;        /* numeric argument */
  574. X
  575. X{
  576. X    register int status;    /* return status */
  577. X    int odisinp;        /* original vlaue of disinp */
  578. X    char key[NPAT];        /* new encryption string */
  579. X
  580. X    /* turn command input echo off */
  581. X    odisinp = disinp;
  582. X    disinp = FALSE;
  583. X
  584. X    /* get the string to use as an encrytion string */
  585. X    status = mlreply("Encryption String: ", key, NPAT - 1);
  586. X    disinp = odisinp;
  587. X        if (status != TRUE)
  588. X                return(status);
  589. X
  590. X    /* and encrypt it */
  591. X    crypt((char *)NULL, 0);
  592. X    crypt(key, strlen(key));
  593. X
  594. X    /* and save it off */
  595. X    strcpy(curbp->b_key, key);
  596. X    mlwrite(" ");        /* clear it off the bottom line */
  597. X    return(TRUE);
  598. X}
  599. X
  600. X/**********
  601. X *
  602. X *    crypt - in place encryption/decryption of a buffer
  603. X *
  604. X *    (C) Copyright 1986, Dana L. Hoggatt
  605. X *    1216, Beck Lane, Lafayette, IN
  606. X *
  607. X *    When consulting directly with the author of this routine, 
  608. X *    please refer to this routine as the "DLH-POLY-86-B CIPHER".  
  609. X *
  610. X *    This routine was written for Dan Lawrence, for use in V3.8 of
  611. X *    MicroEMACS, a public domain text/program editor.  
  612. X *
  613. X *    I kept the following goals in mind when preparing this function:
  614. X *
  615. X *        1.    All printable characters were to be encrypted back
  616. X *        into the printable range, control characters and
  617. X *        high-bit characters were to remain unaffected.  this
  618. X *        way, encrypted would still be just as cheap to 
  619. X *        transmit down a 7-bit data path as they were before.
  620. X *
  621. X *        2.    The encryption had to be portable.  The encrypted 
  622. X *        file from one computer should be able to be decrypted 
  623. X *        on another computer.
  624. X *
  625. X *        3.    The encryption had to be inexpensive, both in terms
  626. X *        of speed and space.
  627. X *
  628. X *        4.    The system needed to be secure against all but the
  629. X *        most determined of attackers.
  630. X *
  631. X *    For encryption of a block of data, one calls crypt passing 
  632. X *    a pointer to the data block and its length. The data block is 
  633. X *    encrypted in place, that is, the encrypted output overwrites 
  634. X *    the input.  Decryption is totally isomorphic, and is performed 
  635. X *    in the same manner by the same routine.  
  636. X *
  637. X *    Before using this routine for encrypting data, you are expected 
  638. X *    to specify an encryption key.  This key is an arbitrary string,
  639. X *    to be supplied by the user.  To set the key takes two calls to 
  640. X *    crypt().  First, you call 
  641. X *
  642. X *        crypt(NULL, vector)
  643. X *
  644. X *    This resets all internal control information.  Typically (and 
  645. X *    specifically in the case on MICRO-emacs) you would use a "vector" 
  646. X *    of 0.  Other values can be used to customize your editor to be 
  647. X *    "incompatable" with the normally distributed version.  For 
  648. X *    this purpose, the best results will be obtained by avoiding
  649. X *    multiples of 95.
  650. X *
  651. X *    Then, you "encrypt" your password by calling 
  652. X *
  653. X *        crypt(pass, strlen(pass))
  654. X *
  655. X *    where "pass" is your password string.  Crypt() will destroy 
  656. X *    the original copy of the password (it becomes encrypted), 
  657. X *    which is good.  You do not want someone on a multiuser system 
  658. X *    to peruse your memory space and bump into your password.  
  659. X *    Still, it is a better idea to erase the password buffer to 
  660. X *    defeat memory perusal by a more technical snooper.  
  661. X *
  662. X *    For the interest of cryptologists, at the heart of this 
  663. X *    function is a Beaufort Cipher.  The cipher alphabet is the 
  664. X *    range of printable characters (' ' to '~'), all "control" 
  665. X *    and "high-bit" characters are left unaltered.
  666. X *
  667. X *    The key is a variant autokey, derived from a wieghted sum 
  668. X *    of all the previous clear text and cipher text.  A counter 
  669. X *    is used as salt to obiterate any simple cyclic behavior 
  670. X *    from the clear text, and key feedback is used to assure 
  671. X *    that the entire message is based on the original key, 
  672. X *    preventing attacks on the last part of the message as if 
  673. X *    it were a pure autokey system.
  674. X *
  675. X *    Overall security of encrypted data depends upon three 
  676. X *    factors:  the fundamental cryptographic system must be 
  677. X *    difficult to compromise; exhaustive searching of the key 
  678. X *    space must be computationally expensive; keys and plaintext 
  679. X *    must remain out of sight.  This system satisfies this set
  680. X *    of conditions to within the degree desired for MicroEMACS.
  681. X *
  682. X *    Though direct methods of attack (against systems such as 
  683. X *    this) do exist, they are not well known and will consume 
  684. X *    considerable amounts of computing time.  An exhaustive
  685. X *    search requires over a billion investigations, on average.
  686. X *
  687. X *    The choice, entry, storage, manipulation, alteration, 
  688. X *    protection and security of the keys themselves are the 
  689. X *    responsiblity of the user.  
  690. X *
  691. X **********/
  692. X
  693. Xcrypt(bptr, len)
  694. Xregister char *bptr;    /* buffer of characters to be encrypted */
  695. Xregister unsigned len;    /* number of characters in the buffer */
  696. X{
  697. X    register int cc;    /* current character being considered */
  698. X
  699. X    static long key = 0;    /* 29 bit encipherment key */
  700. X    static int salt = 0;    /* salt to spice up key with */
  701. X
  702. X    if (!bptr) {        /* is there anything here to encrypt? */
  703. X        key = len;    /* set the new key */
  704. X        salt = len;    /* set the new salt */
  705. X        return;
  706. X    }
  707. X    while (len--) {        /* for every character in the buffer */
  708. X
  709. X        cc = *bptr;    /* get a character out of the buffer */
  710. X
  711. X        /* only encipher printable characters */
  712. X        if ((cc >= ' ') && (cc <= '~')) {
  713. X
  714. X/**  If the upper bit (bit 29) is set, feed it back into the key.  This 
  715. X    assures us that the starting key affects the entire message.  **/
  716. X
  717. X            key &= 0x1FFFFFFFL;    /* strip off overflow */
  718. X            if (key & 0x10000000L) {
  719. X                key ^= 0x0040A001L;    /* feedback */
  720. X            }
  721. X
  722. X/**  Down-bias the character, perform a Beaufort encipherment, and 
  723. X    up-bias the character again.  We want key to be positive 
  724. X    so that the left shift here will be more portable and the 
  725. X    mod95() faster   **/
  726. X
  727. X            cc = mod95((int)(key % 95) - (cc - ' ')) + ' ';
  728. X
  729. X/**  the salt will spice up the key a little bit, helping to obscure 
  730. X    any patterns in the clear text, particularly when all the 
  731. X    characters (or long sequences of them) are the same.  We do 
  732. X    not want the salt to go negative, or it will affect the key 
  733. X    too radically.  It is always a good idea to chop off cyclics 
  734. X    to prime values.  **/
  735. X
  736. X            if (++salt >= 20857) {    /* prime modulus */
  737. X                salt = 0;
  738. X            }
  739. X
  740. X/**  our autokey (a special case of the running key) is being 
  741. X    generated by a wieghted checksum of clear text, cipher 
  742. X    text, and salt.   **/
  743. X
  744. X            key = key + key + cc + *bptr + salt;
  745. X        }
  746. X        *bptr++ = cc;    /* put character back into buffer */
  747. X    }
  748. X    return;
  749. X}
  750. X
  751. Xstatic int mod95(val)
  752. X
  753. Xregister int val;
  754. X
  755. X{
  756. X    /*  The mathematical MOD does not match the computer MOD  */
  757. X
  758. X    /*  Yes, what I do here may look strange, but it gets the
  759. X        job done, and portably at that.  */
  760. X
  761. X    while (val >= 9500)
  762. X        val -= 9500;
  763. X    while (val >= 950)
  764. X        val -= 950;
  765. X    while (val >= 95)
  766. X        val -= 95;
  767. X    while (val < 0)
  768. X        val += 95;
  769. X    return (val);
  770. X}
  771. X#else
  772. Xnocrypt()
  773. X{
  774. X}
  775. X#endif
  776. FRIDAY_NIGHT
  777. echo extracting - dg10.c
  778. sed 's/^X//' > dg10.c << 'FRIDAY_NIGHT'
  779. X/*
  780. X * The routines in this file provide support for the Data General Model 10
  781. X * Microcomputer.
  782. X */
  783. X
  784. X#define    termdef    1            /* don't define "term" external */
  785. X
  786. X#include        <stdio.h>
  787. X#include    "estruct.h"
  788. X#include        "edef.h"
  789. X
  790. X#if     DG10
  791. X
  792. X#define NROW    24                      /* Screen size.                 */
  793. X#define NCOL    80                      /* Edit if you want to.         */
  794. X#define    NPAUSE    100            /* # times thru update to pause */
  795. X#define    MARGIN    8            /* size of minimim margin and    */
  796. X#define    SCRSIZ    64            /* scroll size for extended lines */
  797. X#define BEL     0x07                    /* BEL character.               */
  798. X#define ESC     30                      /* DG10 ESC character.          */
  799. X
  800. Xextern  int     ttopen();               /* Forward references.          */
  801. Xextern  int     ttgetc();
  802. Xextern  int     ttputc();
  803. Xextern  int     ttflush();
  804. Xextern  int     ttclose();
  805. Xextern    int    dg10kopen();
  806. Xextern    int    dg10kclose();
  807. Xextern  int     dg10move();
  808. Xextern  int     dg10eeol();
  809. Xextern  int     dg10eeop();
  810. Xextern  int     dg10beep();
  811. Xextern  int     dg10open();
  812. Xextern    int    dg10rev();
  813. Xextern    int    dg10close();
  814. Xextern    int    dg10cres();
  815. X
  816. X#if    COLOR
  817. Xextern    int    dg10fcol();
  818. Xextern    int    dg10bcol();
  819. X
  820. Xint    cfcolor = -1;        /* current forground color */
  821. Xint    cbcolor = -1;        /* current background color */
  822. Xint    ctrans[] = {        /* emacs -> DG10 color translation table */
  823. X    0, 4, 2, 6, 1, 5, 3, 7};
  824. X#endif
  825. X
  826. X/*
  827. X * Standard terminal interface dispatch table. Most of the fields point into
  828. X * "termio" code.
  829. X */
  830. XTERM    term    = {
  831. X    NROW-1,
  832. X        NROW-1,
  833. X        NCOL,
  834. X        NCOL,
  835. X    MARGIN,
  836. X    SCRSIZ,
  837. X    NPAUSE,
  838. X        dg10open,
  839. X        dg10close,
  840. X    dg10kopen,
  841. X    dg10kclose,
  842. X        ttgetc,
  843. X        ttputc,
  844. X        ttflush,
  845. X        dg10move,
  846. X        dg10eeol,
  847. X        dg10eeop,
  848. X        dg10beep,
  849. X    dg10rev,
  850. X    dg10cres
  851. X#if    COLOR
  852. X    , dg10fcol,
  853. X    dg10bcol
  854. X#endif
  855. X};
  856. X
  857. X#if    COLOR
  858. Xdg10fcol(color)        /* set the current output color */
  859. X
  860. Xint color;    /* color to set */
  861. X
  862. X{
  863. X    if (color == cfcolor)
  864. X        return;
  865. X    ttputc(ESC);
  866. X    ttputc(0101);
  867. X    ttputc(ctrans[color]);
  868. X    cfcolor = color;
  869. X}
  870. X
  871. Xdg10bcol(color)        /* set the current background color */
  872. X
  873. Xint color;    /* color to set */
  874. X
  875. X{
  876. X    if (color == cbcolor)
  877. X        return;
  878. X    ttputc(ESC);
  879. X    ttputc(0102);
  880. X    ttputc(ctrans[color]);
  881. X        cbcolor = color;
  882. X}
  883. X#endif
  884. X
  885. Xdg10move(row, col)
  886. X{
  887. X    ttputc(16);
  888. X        ttputc(col);
  889. X    ttputc(row);
  890. X}
  891. X
  892. Xdg10eeol()
  893. X{
  894. X        ttputc(11);
  895. X}
  896. X
  897. Xdg10eeop()
  898. X{
  899. X#if    COLOR
  900. X    dg10fcol(gfcolor);
  901. X    dg10bcol(gbcolor);
  902. X#endif
  903. X        ttputc(ESC);
  904. X        ttputc(0106);
  905. X        ttputc(0106);
  906. X}
  907. X
  908. Xdg10rev(state)        /* change reverse video state */
  909. X
  910. Xint state;    /* TRUE = reverse, FALSE = normal */
  911. X
  912. X{
  913. X#if    COLOR
  914. X    if (state == TRUE) {
  915. X        dg10fcol(0);
  916. X        dg10bcol(7);
  917. X    }
  918. X#else
  919. X    ttputc(ESC);
  920. X    ttputc(state ? 0104: 0105);
  921. X#endif
  922. X}
  923. X
  924. Xdg10cres()    /* change screen resolution */
  925. X
  926. X{
  927. X    return(TRUE);
  928. X}
  929. X
  930. Xspal()        /* change palette string */
  931. X
  932. X{
  933. X    /*    Does nothing here    */
  934. X}
  935. X
  936. Xdg10beep()
  937. X{
  938. X        ttputc(BEL);
  939. X        ttflush();
  940. X}
  941. X
  942. Xdg10open()
  943. X{
  944. X    strcpy(sres, "NORMAL");
  945. X    revexist = TRUE;
  946. X        ttopen();
  947. X}
  948. X
  949. Xdg10close()
  950. X
  951. X{
  952. X#if    COLOR
  953. X    dg10fcol(7);
  954. X    dg10bcol(0);
  955. X#endif
  956. X    ttclose();
  957. X}
  958. X
  959. Xdg10kopen()
  960. X
  961. X{
  962. X}
  963. X
  964. Xdg10kclose()
  965. X
  966. X{
  967. X}
  968. X
  969. X#if    FLABEL
  970. Xfnclabel(f, n)        /* label a function key */
  971. X
  972. Xint f,n;    /* default flag, numeric argument [unused] */
  973. X
  974. X{
  975. X    /* on machines with no function keys...don't bother */
  976. X    return(TRUE);
  977. X}
  978. X#endif
  979. X#else
  980. Xdg10hello()
  981. X{
  982. X}
  983. X#endif
  984. FRIDAY_NIGHT
  985. echo mes.2 completed!
  986. # That's all folks!
  987.  
  988.  
  989.