home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume6 / uemacs3.7 / part01 next >
Text File  |  1986-11-30  |  48KB  |  1,738 lines

  1. Subject: MicroEmacs, Version 3.7 (uEmacs3.7), Part01/12
  2. Newsgroups: mod.sources
  3. Approved: rs@mirror.UUCP
  4.  
  5. Submitted by: ihnp4!pur-ee!pur-phy!duncan!lawrence
  6. Mod.sources: Volume 6, Issue 71
  7. Archive-name: uEmacs3.7/Part01
  8.  
  9. [  This is the latest revision of one of two programs named "MicroEmacs";
  10.    when discussing these on the net, or in contacting the authors, make
  11.    sure to mention the version number -- in this case 3.7 -- as that is
  12.    the easiest way to distinguish between them.  Lawrence will be posting
  13.    uuencoded executables in net.micro.pc and net.micro.amiga; the file
  14.    'readme' contains information on how to also get these from him
  15.    directly.   --r$ ]
  16.  
  17. echo extracting - Makefile
  18. sed 's/^X//' > Makefile << 'FRIDAY_NIGHT'
  19. XCFLAGS=        -O -I/usr/tools/include/bland
  20. X
  21. XOFILES=        ansi.o basic.o bind.o buffer.o display.o file.o \
  22. X        fileio.o hp150.o line.o lock.c main.o random.o region.o \
  23. X        search.o spawn.o tcap.o termio.o vt52.o window.o word.o \
  24. X        exec.o input.o isearch.o
  25. X
  26. XCFILES=        ansi.c basic.c bind.c buffer.c display.c  file.c \
  27. X        fileio.c hp150.c line.c lock.c main.c random.c region.c \
  28. X        search.c spawn.c tcap.c termio.c vt52.c window.c word.c \
  29. X        exec.c input.c isearch.c
  30. X
  31. XHFILES=        estruct.h edef.h efunc.h epath.h
  32. X
  33. Xemacs:        $(OFILES)
  34. X        $(CC) $(CFLAGS) $(OFILES) -ltermcap -lc -o emacs
  35. X
  36. X$(OFILES):    $(HFILES)
  37. FRIDAY_NIGHT
  38. echo extracting - ansi.c
  39. sed 's/^X//' > ansi.c << 'FRIDAY_NIGHT'
  40. X/*
  41. X * The routines in this file provide support for ANSI style terminals
  42. X * over a serial line. The serial I/O services are provided by routines in
  43. X * "termio.c". It compiles into nothing if not an ANSI device.
  44. X */
  45. X
  46. X#define    termdef    1            /* don't define "term" external */
  47. X
  48. X#include        <stdio.h>
  49. X#include    "estruct.h"
  50. X#include        "edef.h"
  51. X
  52. X#if     ANSI
  53. X
  54. X#if    AMIGA
  55. X#define NROW    23                      /* Screen size.                 */
  56. X#define NCOL    77                      /* Edit if you want to.         */
  57. X#else
  58. X#define NROW    25                      /* Screen size.                 */
  59. X#define NCOL    80                      /* Edit if you want to.         */
  60. X#endif
  61. X#define    NPAUSE    100            /* # times thru update to pause */
  62. X#define    MARGIN    8            /* size of minimim margin and    */
  63. X#define    SCRSIZ    64            /* scroll size for extended lines */
  64. X#define BEL     0x07                    /* BEL character.               */
  65. X#define ESC     0x1B                    /* ESC character.               */
  66. X
  67. Xextern  int     ttopen();               /* Forward references.          */
  68. Xextern  int     ttgetc();
  69. Xextern  int     ttputc();
  70. Xextern  int     ttflush();
  71. Xextern  int     ttclose();
  72. Xextern  int     ansimove();
  73. Xextern  int     ansieeol();
  74. Xextern  int     ansieeop();
  75. Xextern  int     ansibeep();
  76. Xextern  int     ansiopen();
  77. Xextern    int    ansirev();
  78. Xextern    int    ansiclose();
  79. X
  80. X#if    COLOR
  81. Xextern    int    ansifcol();
  82. Xextern    int    ansibcol();
  83. X
  84. Xint    cfcolor = -1;        /* current forground color */
  85. Xint    cbcolor = -1;        /* current background color */
  86. X#endif
  87. X
  88. X/*
  89. X * Standard terminal interface dispatch table. Most of the fields point into
  90. X * "termio" code.
  91. X */
  92. XTERM    term    = {
  93. X        NROW-1,
  94. X        NCOL,
  95. X    MARGIN,
  96. X    SCRSIZ,
  97. X    NPAUSE,
  98. X        ansiopen,
  99. X        ansiclose,
  100. X        ttgetc,
  101. X        ttputc,
  102. X        ttflush,
  103. X        ansimove,
  104. X        ansieeol,
  105. X        ansieeop,
  106. X        ansibeep,
  107. X    ansirev
  108. X#if    COLOR
  109. X    , ansifcol,
  110. X    ansibcol
  111. X#endif
  112. X};
  113. X
  114. X#if    COLOR
  115. Xansifcol(color)        /* set the current output color */
  116. X
  117. Xint color;    /* color to set */
  118. X
  119. X{
  120. X    if (color == cfcolor)
  121. X        return;
  122. X    ttputc(ESC);
  123. X    ttputc('[');
  124. X    ansiparm(color+30);
  125. X    ttputc('m');
  126. X    cfcolor = color;
  127. X}
  128. X
  129. Xansibcol(color)        /* set the current background color */
  130. X
  131. Xint color;    /* color to set */
  132. X
  133. X{
  134. X    if (color == cbcolor)
  135. X        return;
  136. X    ttputc(ESC);
  137. X    ttputc('[');
  138. X    ansiparm(color+40);
  139. X    ttputc('m');
  140. X        cbcolor = color;
  141. X}
  142. X#endif
  143. X
  144. Xansimove(row, col)
  145. X{
  146. X        ttputc(ESC);
  147. X        ttputc('[');
  148. X        ansiparm(row+1);
  149. X        ttputc(';');
  150. X        ansiparm(col+1);
  151. X        ttputc('H');
  152. X}
  153. X
  154. Xansieeol()
  155. X{
  156. X        ttputc(ESC);
  157. X        ttputc('[');
  158. X        ttputc('K');
  159. X}
  160. X
  161. Xansieeop()
  162. X{
  163. X#if    COLOR
  164. X    ansifcol(gfcolor);
  165. X    ansibcol(gbcolor);
  166. X#endif
  167. X        ttputc(ESC);
  168. X        ttputc('[');
  169. X        ttputc('J');
  170. X}
  171. X
  172. Xansirev(state)        /* change reverse video state */
  173. X
  174. Xint state;    /* TRUE = reverse, FALSE = normal */
  175. X
  176. X{
  177. X#if    COLOR
  178. X    int ftmp, btmp;        /* temporaries for colors */
  179. X#endif
  180. X
  181. X    ttputc(ESC);
  182. X    ttputc('[');
  183. X    ttputc(state ? '7': '0');
  184. X    ttputc('m');
  185. X#if    COLOR
  186. X    if (state == FALSE) {
  187. X        ftmp = cfcolor;
  188. X        btmp = cbcolor;
  189. X        cfcolor = -1;
  190. X        cbcolor = -1;
  191. X        ansifcol(ftmp);
  192. X        ansibcol(btmp);
  193. X    }
  194. X#endif
  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    revexist = TRUE;
  235. X        ttopen();
  236. X}
  237. X
  238. Xansiclose()
  239. X
  240. X{
  241. X#if    COLOR
  242. X    ansifcol(7);
  243. X    ansibcol(0);
  244. X#endif
  245. X    ttclose();
  246. X}
  247. X#else
  248. Xansihello()
  249. X{
  250. X}
  251. X#endif
  252. FRIDAY_NIGHT
  253. echo extracting - azmap.cmd
  254. sed 's/^X//' > azmap.cmd << 'FRIDAY_NIGHT'
  255. X;    AZMAP.CMD:    MicroEMACS Macro file
  256. X;            to translate an AZTEC C .SYM map file into
  257. X;            the form needed to read it into ADDSYMS
  258. X;            to be used with Pheonix's PFIX plus (C) debugger
  259. X;
  260. X;            written 6/5/86 by Daniel Lawrence
  261. X
  262. Xbegining-of-file
  263. Xnewline
  264. Xprevious-line
  265. Xreplace-string ~n "~n 0000:"
  266. Xbegining-of-line
  267. Xkill-to-end-of-line
  268. Xnewline
  269. Xnewline
  270. Xnewline
  271. Xbegining-of-file
  272. Xnewline
  273. Xinsert-string "  Address         Publics by Name"
  274. Xnewline
  275. Xset-mark
  276. Xend-of-file
  277. Xcase-region-upper
  278. Xbegining-of-file
  279. Xreplace-string _~n ~n
  280. X
  281. FRIDAY_NIGHT
  282. echo extracting - basic.c
  283. sed 's/^X//' > basic.c << 'FRIDAY_NIGHT'
  284. X/*
  285. X * The routines in this file move the cursor around on the screen. They
  286. X * compute a new value for the cursor, then adjust ".". The display code
  287. X * always updates the cursor location, so only moves between lines, or
  288. X * functions that adjust the top line in the window and invalidate the
  289. X * framing, are hard.
  290. X */
  291. X#include        <stdio.h>
  292. X#include    "estruct.h"
  293. X#include        "edef.h"
  294. X
  295. X/*
  296. X * Move the cursor to the
  297. X * beginning of the current line.
  298. X * Trivial.
  299. X */
  300. Xgotobol(f, n)
  301. X{
  302. X        curwp->w_doto  = 0;
  303. X        return (TRUE);
  304. X}
  305. X
  306. X/*
  307. X * Move the cursor backwards by "n" characters. If "n" is less than zero call
  308. X * "forwchar" to actually do the move. Otherwise compute the new cursor
  309. X * location. Error if you try and move out of the buffer. Set the flag if the
  310. X * line pointer for dot changes.
  311. X */
  312. Xbackchar(f, n)
  313. Xregister int    n;
  314. X{
  315. X        register LINE   *lp;
  316. X
  317. X        if (n < 0)
  318. X                return (forwchar(f, -n));
  319. X        while (n--) {
  320. X                if (curwp->w_doto == 0) {
  321. X                        if ((lp=lback(curwp->w_dotp)) == curbp->b_linep)
  322. X                                return (FALSE);
  323. X                        curwp->w_dotp  = lp;
  324. X                        curwp->w_doto  = llength(lp);
  325. X                        curwp->w_flag |= WFMOVE;
  326. X                } else
  327. X                        curwp->w_doto--;
  328. X        }
  329. X        return (TRUE);
  330. X}
  331. X
  332. X/*
  333. X * Move the cursor to the end of the current line. Trivial. No errors.
  334. X */
  335. Xgotoeol(f, n)
  336. X{
  337. X        curwp->w_doto  = llength(curwp->w_dotp);
  338. X        return (TRUE);
  339. X}
  340. X
  341. X/*
  342. X * Move the cursor forwwards by "n" characters. If "n" is less than zero call
  343. X * "backchar" to actually do the move. Otherwise compute the new cursor
  344. X * location, and move ".". Error if you try and move off the end of the
  345. X * buffer. Set the flag if the line pointer for dot changes.
  346. X */
  347. Xforwchar(f, n)
  348. Xregister int    n;
  349. X{
  350. X        if (n < 0)
  351. X                return (backchar(f, -n));
  352. X        while (n--) {
  353. X                if (curwp->w_doto == llength(curwp->w_dotp)) {
  354. X                        if (curwp->w_dotp == curbp->b_linep)
  355. X                                return (FALSE);
  356. X                        curwp->w_dotp  = lforw(curwp->w_dotp);
  357. X                        curwp->w_doto  = 0;
  358. X                        curwp->w_flag |= WFMOVE;
  359. X                } else
  360. X                        curwp->w_doto++;
  361. X        }
  362. X        return (TRUE);
  363. X}
  364. X
  365. Xgotoline(f, n)        /* move to a particular line.
  366. X               argument (n) must be a positive integer for
  367. X               this to actually do anything        */
  368. X
  369. X{
  370. X    if (n < 1)        /* if a bogus argument...then leave */
  371. X        return(FALSE);
  372. X
  373. X    /* first, we go to the start of the buffer */
  374. X        curwp->w_dotp  = lforw(curbp->b_linep);
  375. X        curwp->w_doto  = 0;
  376. X    return(forwline(f, n-1));
  377. X}
  378. X
  379. X/*
  380. X * Goto the beginning of the buffer. Massive adjustment of dot. This is
  381. X * considered to be hard motion; it really isn't if the original value of dot
  382. X * is the same as the new value of dot. Normally bound to "M-<".
  383. X */
  384. Xgotobob(f, n)
  385. X{
  386. X        curwp->w_dotp  = lforw(curbp->b_linep);
  387. X        curwp->w_doto  = 0;
  388. X        curwp->w_flag |= WFHARD;
  389. X        return (TRUE);
  390. X}
  391. X
  392. X/*
  393. X * Move to the end of the buffer. Dot is always put at the end of the file
  394. X * (ZJ). The standard screen code does most of the hard parts of update.
  395. X * Bound to "M->".
  396. X */
  397. Xgotoeob(f, n)
  398. X{
  399. X        curwp->w_dotp  = curbp->b_linep;
  400. X        curwp->w_doto  = 0;
  401. X        curwp->w_flag |= WFHARD;
  402. X        return (TRUE);
  403. X}
  404. X
  405. X/*
  406. X * Move forward by full lines. If the number of lines to move is less than
  407. X * zero, call the backward line function to actually do it. The last command
  408. X * controls how the goal column is set. Bound to "C-N". No errors are
  409. X * possible.
  410. X */
  411. Xforwline(f, n)
  412. X{
  413. X        register LINE   *dlp;
  414. X
  415. X        if (n < 0)
  416. X                return (backline(f, -n));
  417. X        if ((lastflag&CFCPCN) == 0)             /* Reset goal if last   */
  418. X                curgoal = getccol(FALSE);       /* not C-P or C-N       */
  419. X        thisflag |= CFCPCN;
  420. X        dlp = curwp->w_dotp;
  421. X        while (n-- && dlp!=curbp->b_linep)
  422. X                dlp = lforw(dlp);
  423. X        curwp->w_dotp  = dlp;
  424. X        curwp->w_doto  = getgoal(dlp);
  425. X        curwp->w_flag |= WFMOVE;
  426. X        return (TRUE);
  427. X}
  428. X
  429. X/*
  430. X * This function is like "forwline", but goes backwards. The scheme is exactly
  431. X * the same. Check for arguments that are less than zero and call your
  432. X * alternate. Figure out the new line and call "movedot" to perform the
  433. X * motion. No errors are possible. Bound to "C-P".
  434. X */
  435. Xbackline(f, n)
  436. X{
  437. X        register LINE   *dlp;
  438. X
  439. X        if (n < 0)
  440. X                return (forwline(f, -n));
  441. X        if ((lastflag&CFCPCN) == 0)             /* Reset goal if the    */
  442. X                curgoal = getccol(FALSE);       /* last isn't C-P, C-N  */
  443. X        thisflag |= CFCPCN;
  444. X        dlp = curwp->w_dotp;
  445. X        while (n-- && lback(dlp)!=curbp->b_linep)
  446. X                dlp = lback(dlp);
  447. X        curwp->w_dotp  = dlp;
  448. X        curwp->w_doto  = getgoal(dlp);
  449. X        curwp->w_flag |= WFMOVE;
  450. X        return (TRUE);
  451. X}
  452. X
  453. X#if    WORDPRO
  454. Xgotobop(f, n)    /* go back to the begining of the current paragraph
  455. X           here we look for a <NL><NL> or <NL><TAB> or <NL><SPACE>
  456. X           combination to delimit the begining of a paragraph    */
  457. X
  458. Xint f, n;    /* default Flag & Numeric argument */
  459. X
  460. X{
  461. X    register int suc;    /* success of last backchar */
  462. X
  463. X    if (n < 0)    /* the other way...*/
  464. X        return(gotoeop(f, -n));
  465. X
  466. X    while (n-- > 0) {    /* for each one asked for */
  467. X
  468. X        /* first scan back until we are in a word */
  469. X        suc = backchar(FALSE, 1);
  470. X        while (!inword() && suc)
  471. X            suc = backchar(FALSE, 1);
  472. X        curwp->w_doto = 0;    /* and go to the B-O-Line */
  473. X
  474. X        /* and scan back until we hit a <NL><NL> or <NL><TAB>
  475. X           or a <NL><SPACE>                    */
  476. X        while (lback(curwp->w_dotp) != curbp->b_linep)
  477. X            if (llength(curwp->w_dotp) != 0 &&
  478. X                lgetc(curwp->w_dotp, curwp->w_doto) != TAB &&
  479. X                lgetc(curwp->w_dotp, curwp->w_doto) != ' ')
  480. X                curwp->w_dotp = lback(curwp->w_dotp);
  481. X            else
  482. X                break;
  483. X
  484. X        /* and then forward until we are in a word */
  485. X        suc = forwchar(FALSE, 1);
  486. X        while (suc && !inword())
  487. X            suc = forwchar(FALSE, 1);
  488. X    }
  489. X    curwp->w_flag |= WFMOVE;    /* force screen update */
  490. X    return(TRUE);
  491. X}
  492. X
  493. Xgotoeop(f, n)    /* go forword to the end of the current paragraph
  494. X           here we look for a <NL><NL> or <NL><TAB> or <NL><SPACE>
  495. X           combination to delimit the begining of a paragraph    */
  496. X
  497. Xint f, n;    /* default Flag & Numeric argument */
  498. X
  499. X{
  500. X    register int suc;    /* success of last backchar */
  501. X
  502. X    if (n < 0)    /* the other way...*/
  503. X        return(gotobop(f, -n));
  504. X
  505. X    while (n-- > 0) {    /* for each one asked for */
  506. X
  507. X        /* first scan forward until we are in a word */
  508. X        suc = forwchar(FALSE, 1);
  509. X        while (!inword() && suc)
  510. X            suc = forwchar(FALSE, 1);
  511. X        curwp->w_doto = 0;    /* and go to the B-O-Line */
  512. X        if (suc)    /* of next line if not at EOF */
  513. X            curwp->w_dotp = lforw(curwp->w_dotp);
  514. X
  515. X        /* and scan forword until we hit a <NL><NL> or <NL><TAB>
  516. X           or a <NL><SPACE>                    */
  517. X        while (curwp->w_dotp != curbp->b_linep) {
  518. X            if (llength(curwp->w_dotp) != 0 &&
  519. X                lgetc(curwp->w_dotp, curwp->w_doto) != TAB &&
  520. X                lgetc(curwp->w_dotp, curwp->w_doto) != ' ')
  521. X                curwp->w_dotp = lforw(curwp->w_dotp);
  522. X            else
  523. X                break;
  524. X        }
  525. X
  526. X        /* and then backward until we are in a word */
  527. X        suc = backchar(FALSE, 1);
  528. X        while (suc && !inword()) {
  529. X            suc = backchar(FALSE, 1);
  530. X        }
  531. X        curwp->w_doto = llength(curwp->w_dotp);    /* and to the EOL */
  532. X    }
  533. X    curwp->w_flag |= WFMOVE;    /* force screen update */
  534. X    return(TRUE);
  535. X}
  536. X#endif
  537. X
  538. X/*
  539. X * This routine, given a pointer to a LINE, and the current cursor goal
  540. X * column, return the best choice for the offset. The offset is returned.
  541. X * Used by "C-N" and "C-P".
  542. X */
  543. Xgetgoal(dlp)
  544. Xregister LINE   *dlp;
  545. X{
  546. X        register int    c;
  547. X        register int    col;
  548. X        register int    newcol;
  549. X        register int    dbo;
  550. X
  551. X        col = 0;
  552. X        dbo = 0;
  553. X        while (dbo != llength(dlp)) {
  554. X                c = lgetc(dlp, dbo);
  555. X                newcol = col;
  556. X                if (c == '\t')
  557. X                        newcol |= 0x07;
  558. X                else if (c<0x20 || c==0x7F)
  559. X                        ++newcol;
  560. X                ++newcol;
  561. X                if (newcol > curgoal)
  562. X                        break;
  563. X                col = newcol;
  564. X                ++dbo;
  565. X        }
  566. X        return (dbo);
  567. X}
  568. X
  569. X/*
  570. X * Scroll forward by a specified number of lines, or by a full page if no
  571. X * argument. Bound to "C-V". The "2" in the arithmetic on the window size is
  572. X * the overlap; this value is the default overlap value in ITS EMACS. Because
  573. X * this zaps the top line in the display window, we have to do a hard update.
  574. X */
  575. Xforwpage(f, n)
  576. Xregister int    n;
  577. X{
  578. X        register LINE   *lp;
  579. X
  580. X        if (f == FALSE) {
  581. X                n = curwp->w_ntrows - 2;        /* Default scroll.      */
  582. X                if (n <= 0)                     /* Forget the overlap   */
  583. X                        n = 1;                  /* if tiny window.      */
  584. X        } else if (n < 0)
  585. X                return (backpage(f, -n));
  586. X#if     CVMVAS
  587. X        else                                    /* Convert from pages   */
  588. X                n *= curwp->w_ntrows;           /* to lines.            */
  589. X#endif
  590. X        lp = curwp->w_linep;
  591. X        while (n-- && lp!=curbp->b_linep)
  592. X                lp = lforw(lp);
  593. X        curwp->w_linep = lp;
  594. X        curwp->w_dotp  = lp;
  595. X        curwp->w_doto  = 0;
  596. X        curwp->w_flag |= WFHARD;
  597. X        return (TRUE);
  598. X}
  599. X
  600. X/*
  601. X * This command is like "forwpage", but it goes backwards. The "2", like
  602. X * above, is the overlap between the two windows. The value is from the ITS
  603. X * EMACS manual. Bound to "M-V". We do a hard update for exactly the same
  604. X * reason.
  605. X */
  606. Xbackpage(f, n)
  607. Xregister int    n;
  608. X{
  609. X        register LINE   *lp;
  610. X
  611. X        if (f == FALSE) {
  612. X                n = curwp->w_ntrows - 2;        /* Default scroll.      */
  613. X                if (n <= 0)                     /* Don't blow up if the */
  614. X                        n = 1;                  /* window is tiny.      */
  615. X        } else if (n < 0)
  616. X                return (forwpage(f, -n));
  617. X#if     CVMVAS
  618. X        else                                    /* Convert from pages   */
  619. X                n *= curwp->w_ntrows;           /* to lines.            */
  620. X#endif
  621. X        lp = curwp->w_linep;
  622. X        while (n-- && lback(lp)!=curbp->b_linep)
  623. X                lp = lback(lp);
  624. X        curwp->w_linep = lp;
  625. X        curwp->w_dotp  = lp;
  626. X        curwp->w_doto  = 0;
  627. X        curwp->w_flag |= WFHARD;
  628. X        return (TRUE);
  629. X}
  630. X
  631. X/*
  632. X * Set the mark in the current window to the value of "." in the window. No
  633. X * errors are possible. Bound to "M-.".
  634. X */
  635. Xsetmark(f, n)
  636. X{
  637. X        curwp->w_markp = curwp->w_dotp;
  638. X        curwp->w_marko = curwp->w_doto;
  639. X        mlwrite("[Mark set]");
  640. X        return (TRUE);
  641. X}
  642. X
  643. X/*
  644. X * Swap the values of "." and "mark" in the current window. This is pretty
  645. X * easy, bacause all of the hard work gets done by the standard routine
  646. X * that moves the mark about. The only possible error is "no mark". Bound to
  647. X * "C-X C-X".
  648. X */
  649. Xswapmark(f, n)
  650. X{
  651. X        register LINE   *odotp;
  652. X        register int    odoto;
  653. X
  654. X        if (curwp->w_markp == NULL) {
  655. X                mlwrite("No mark in this window");
  656. X                return (FALSE);
  657. X        }
  658. X        odotp = curwp->w_dotp;
  659. X        odoto = curwp->w_doto;
  660. X        curwp->w_dotp  = curwp->w_markp;
  661. X        curwp->w_doto  = curwp->w_marko;
  662. X        curwp->w_markp = odotp;
  663. X        curwp->w_marko = odoto;
  664. X        curwp->w_flag |= WFMOVE;
  665. X        return (TRUE);
  666. X}
  667. FRIDAY_NIGHT
  668. echo extracting - bind.c
  669. sed 's/^X//' > bind.c << 'FRIDAY_NIGHT'
  670. X/*    This file is for functions having to do with key bindings,
  671. X    descriptions, help commands and startup file.
  672. X
  673. X    written 11-feb-86 by Daniel Lawrence
  674. X                                */
  675. X
  676. X#include    <stdio.h>
  677. X#include    "estruct.h"
  678. X#include    "edef.h"
  679. X#include    "epath.h"
  680. X
  681. Xextern int meta(), cex();    /* dummy prefix binding functions */
  682. X
  683. Xdeskey(f, n)    /* describe the command for a certain key */
  684. X
  685. X{
  686. X    register int c;        /* command character to describe */
  687. X    register char *ptr;    /* string pointer to scan output strings */
  688. X    register KEYTAB *ktp;    /* pointer into the command table */
  689. X    register int found;    /* matched command flag */
  690. X    register NBIND *nptr;    /* pointer into the name binding table */
  691. X    char outseq[80];    /* output buffer for command sequence */
  692. X
  693. X    /* prompt the user to type us a key to describe */
  694. X    mlwrite(": describe-key ");
  695. X
  696. X    /* get the command sequence to describe */
  697. X    c = getckey(FALSE);            /* get a command sequence */
  698. X
  699. X    /* change it to something we can print as well */
  700. X    cmdstr(c, &outseq[0]);
  701. X
  702. X    /* and dump it out */
  703. X    ptr = &outseq[0];
  704. X    while (*ptr)
  705. X        (*term.t_putchar)(*ptr++);
  706. X    (*term.t_putchar)(' ');        /* space it out */
  707. X
  708. X    /* find the right ->function */
  709. X    ktp = &keytab[0];
  710. X    found = FALSE;
  711. X    while (ktp->k_fp != NULL) {
  712. X        if (ktp->k_code == c) {
  713. X            found = TRUE;
  714. X            break;
  715. X        }
  716. X        ++ktp;
  717. X    }
  718. X
  719. X    if (!found)
  720. X        strcpy(outseq,"Not Bound");
  721. X    else {
  722. X        /* match it against the name binding table */
  723. X        nptr = &names[0];
  724. X        strcpy(outseq,"[Bad binding]");
  725. X        while (nptr->n_func != NULL) {
  726. X            if (nptr->n_func == ktp->k_fp) {
  727. X                strcpy(outseq, nptr->n_name);
  728. X                break;
  729. X            }
  730. X            ++nptr;
  731. X        }
  732. X    }
  733. X
  734. X    /* output the command sequence */
  735. X    ptr = &outseq[0];
  736. X    while (*ptr)
  737. X        (*term.t_putchar)(*ptr++);
  738. X}
  739. X
  740. Xcmdstr(c, seq)    /* change a key command to a string we can print out */
  741. X
  742. Xint c;        /* sequence to translate */
  743. Xchar *seq;    /* destination string for sequence */
  744. X
  745. X{
  746. X    char *ptr;    /* pointer into current position in sequence */
  747. X
  748. X    ptr = seq;
  749. X
  750. X    /* apply meta sequence if needed */
  751. X    if (c & META) {
  752. X        *ptr++ = 'M';
  753. X        *ptr++ = '-';
  754. X    }
  755. X
  756. X    /* apply ^X sequence if needed */
  757. X    if (c & CTLX) {
  758. X        *ptr++ = '^';
  759. X        *ptr++ = 'X';
  760. X    }
  761. X
  762. X    /* apply SPEC sequence if needed */
  763. X    if (c & SPEC) {
  764. X        *ptr++ = 'F';
  765. X        *ptr++ = 'N';
  766. X    }
  767. X
  768. X    /* apply control sequence if needed */
  769. X    if (c & CTRL) {
  770. X        *ptr++ = '^';
  771. X    }
  772. X
  773. X    c = c & 255;    /* strip the prefixes */
  774. X
  775. X    /* and output the final sequence */
  776. X
  777. X    *ptr++ = c;
  778. X    *ptr = 0;    /* terminate the string */
  779. X}
  780. X
  781. Xhelp(f, n)    /* give me some help!!!!
  782. X           bring up a fake buffer and read the help file
  783. X           into it with view mode            */
  784. X{
  785. X    register int status;    /* status of I/O operations */
  786. X    register WINDOW *wp;    /* scaning pointer to windows */
  787. X    register BUFFER *bp;    /* buffer pointer to help */
  788. X    register int i;        /* index into help file names */
  789. X    char fname[NSTRING];    /* buffer to construct file name in */
  790. X
  791. X    /* first check if we are already here */
  792. X    bp = bfind("emacs.hlp", FALSE, BFINVS);
  793. X
  794. X    if (bp == NULL) {
  795. X        /* search through the list of help files */
  796. X        for (i=2; i < NPNAMES; i++) {
  797. X            strcpy(fname, pathname[i]);
  798. X            strcat(fname, pathname[1]);
  799. X            status = ffropen(fname);
  800. X            if (status == FIOSUC)
  801. X                break;
  802. X        }
  803. X
  804. X        if (status == FIOFNF) {
  805. X            mlwrite("[Help file is not online]");
  806. X            return(FALSE);
  807. X        }
  808. X
  809. X        /* close the file to prepare for to read it in */
  810. X        ffclose();
  811. X    }
  812. X
  813. X    /* split the current window to make room for the help stuff */
  814. X    if (splitwind(FALSE, 1) == FALSE)
  815. X            return(FALSE);
  816. X
  817. X    if (bp == NULL) {
  818. X        /* and read the stuff in */
  819. X        if (getfile(fname, FALSE) == FALSE)
  820. X            return(FALSE);
  821. X    } else
  822. X        swbuffer(bp);
  823. X
  824. X    /* make this window in VIEW mode, update all mode lines */
  825. X    curwp->w_bufp->b_mode |= MDVIEW;
  826. X    curwp->w_bufp->b_flag |= BFINVS;
  827. X    wp = wheadp;
  828. X    while (wp != NULL) {
  829. X        wp->w_flag |= WFMODE;
  830. X        wp = wp->w_wndp;
  831. X    }
  832. X    return(TRUE);
  833. X}
  834. X
  835. Xint (*fncmatch(fname))() /* match fname to a function in the names table
  836. X                and return any match or NULL if none        */
  837. X
  838. Xchar *fname;    /* name to attempt to match */
  839. X
  840. X{
  841. X    register NBIND *ffp;    /* pointer to entry in name binding table */
  842. X
  843. X    /* scan through the table, returning any match */
  844. X    ffp = &names[0];
  845. X    while (ffp->n_func != NULL) {
  846. X        if (strcmp(fname, ffp->n_name) == 0)
  847. X            return(ffp->n_func);
  848. X        ++ffp;
  849. X    }
  850. X    return(NULL);
  851. X}
  852. X
  853. X/* bindtokey:    add a new key to the key binding table
  854. X*/
  855. X
  856. Xbindtokey(f, n)
  857. X
  858. Xint f, n;    /* command arguments [IGNORED] */
  859. X
  860. X{
  861. X    register int c;        /* command key to bind */
  862. X    register (*kfunc)();    /* ptr to the requexted function to bind to */
  863. X    register char *ptr;    /* ptr to dump out input key string */
  864. X    register KEYTAB *ktp;    /* pointer into the command table */
  865. X    register int found;    /* matched command flag */
  866. X    char outseq[80];    /* output buffer for keystroke sequence */
  867. X    int (*getname())();
  868. X
  869. X    /* prompt the user to type in a key to bind */
  870. X    mlwrite(": bind-to-key ");
  871. X
  872. X    /* get the function name to bind it to */
  873. X    kfunc = getname();
  874. X    if (kfunc == NULL) {
  875. X        mlwrite("[No such function]");
  876. X        return(FALSE);
  877. X    }
  878. X    (*term.t_putchar)(' ');        /* space it out */
  879. X    (*term.t_flush)();
  880. X
  881. X    /* get the command sequence to bind */
  882. X    c = getckey((kfunc == meta) || (kfunc == cex));
  883. X
  884. X    /* change it to something we can print as well */
  885. X    cmdstr(c, &outseq[0]);
  886. X
  887. X    /* and dump it out */
  888. X    ptr = &outseq[0];
  889. X    while (*ptr)
  890. X        (*term.t_putchar)(*ptr++);
  891. X
  892. X    /* if the function is a prefix key */
  893. X    if (kfunc == meta || kfunc == cex) {
  894. X
  895. X        /* search for an existing binding for the prefix key */
  896. X        ktp = &keytab[0];
  897. X        found = FALSE;
  898. X        while (ktp->k_fp != NULL) {
  899. X            if (ktp->k_fp == kfunc) {
  900. X                found = TRUE;
  901. X                break;
  902. X            }
  903. X            ++ktp;
  904. X        }
  905. X
  906. X        /* reset the appropriate global prefix variable */
  907. X        if (kfunc == meta)
  908. X            metac = c;
  909. X        if (kfunc == cex)
  910. X            ctlxc = c;
  911. X
  912. X        /* if we found it, just reset it
  913. X           otherwise, let it fall through and be added to the end */
  914. X        if (found) {
  915. X            ktp->k_code = c;
  916. X            return(TRUE);
  917. X        }
  918. X    } else {
  919. X
  920. X        /* search the table to see if it exists */
  921. X        ktp = &keytab[0];
  922. X        found = FALSE;
  923. X        while (ktp->k_fp != NULL) {
  924. X            if (ktp->k_code == c) {
  925. X                found = TRUE;
  926. X                break;
  927. X            }
  928. X            ++ktp;
  929. X        }
  930. X    }
  931. X
  932. X    if (found) {    /* it exists, just change it then */
  933. X        ktp->k_fp = kfunc;
  934. X    } else {    /* otherwise we need to add it to the end */
  935. X        /* if we run out of binding room, bitch */
  936. X        if (ktp >= &keytab[NBINDS]) {
  937. X            mlwrite("Binding table FULL!");
  938. X            return(FALSE);
  939. X        }
  940. X
  941. X        ktp->k_code = c;    /* add keycode */
  942. X        ktp->k_fp = kfunc;    /* and the function pointer */
  943. X        ++ktp;            /* and make sure the next is null */
  944. X        ktp->k_code = 0;
  945. X        ktp->k_fp = NULL;
  946. X    }
  947. X    return(TRUE);
  948. X}
  949. X
  950. X/* unbindkey:    delete a key from the key binding table
  951. X*/
  952. X
  953. Xunbindkey(f, n)
  954. X
  955. Xint f, n;    /* command arguments [IGNORED] */
  956. X
  957. X{
  958. X    register int c;        /* command key to unbind */
  959. X    register char *ptr;    /* ptr to dump out input key string */
  960. X    register KEYTAB *ktp;    /* pointer into the command table */
  961. X    register KEYTAB *sktp;    /* saved pointer into the command table */
  962. X    register int found;    /* matched command flag */
  963. X    char outseq[80];    /* output buffer for keystroke sequence */
  964. X
  965. X    /* prompt the user to type in a key to unbind */
  966. X    mlwrite(": unbind-key ");
  967. X
  968. X    /* get the command sequence to unbind */
  969. X    c = getckey(FALSE);        /* get a command sequence */
  970. X
  971. X    /* change it to something we can print as well */
  972. X    cmdstr(c, &outseq[0]);
  973. X
  974. X    /* and dump it out */
  975. X    ptr = &outseq[0];
  976. X    while (*ptr)
  977. X        (*term.t_putchar)(*ptr++);
  978. X
  979. X    /* search the table to see if the key exists */
  980. X    ktp = &keytab[0];
  981. X    found = FALSE;
  982. X    while (ktp->k_fp != NULL) {
  983. X        if (ktp->k_code == c) {
  984. X            found = TRUE;
  985. X            break;
  986. X        }
  987. X        ++ktp;
  988. X    }
  989. X
  990. X    /* if it isn't bound, bitch */
  991. X    if (!found) {
  992. X        mlwrite("[Key not bound]");
  993. X        return(FALSE);
  994. X    }
  995. X
  996. X    /* save the pointer and scan to the end of the table */
  997. X    sktp = ktp;
  998. X    while (ktp->k_fp != NULL)
  999. X        ++ktp;
  1000. X    --ktp;        /* backup to the last legit entry */
  1001. X
  1002. X    /* copy the last entry to the current one */
  1003. X    sktp->k_code = ktp->k_code;
  1004. X    sktp->k_fp   = ktp->k_fp;
  1005. X
  1006. X    /* null out the last one */
  1007. X    ktp->k_code = 0;
  1008. X    ktp->k_fp = NULL;
  1009. X    return(TRUE);
  1010. X}
  1011. X
  1012. Xdesbind(f, n)    /* describe bindings
  1013. X           bring up a fake buffer and list the key bindings
  1014. X           into it with view mode            */
  1015. X{
  1016. X    register WINDOW *wp;    /* scnaning pointer to windows */
  1017. X    register KEYTAB *ktp;    /* pointer into the command table */
  1018. X    register NBIND *nptr;    /* pointer into the name binding table */
  1019. X    register BUFFER *bp;    /* buffer to put binding list into */
  1020. X    char *strp;        /* pointer int string to send */
  1021. X    int cpos;        /* current position to use in outseq */
  1022. X    char outseq[80];    /* output buffer for keystroke sequence */
  1023. X
  1024. X    /* split the current window to make room for the binding list */
  1025. X    if (splitwind(FALSE, 1) == FALSE)
  1026. X            return(FALSE);
  1027. X
  1028. X    /* and get a buffer for it */
  1029. X    bp = bfind("Binding list", TRUE, 0);
  1030. X    if (bp == NULL || bclear(bp) == FALSE) {
  1031. X        mlwrite("Can not display binding list");
  1032. X        return(FALSE);
  1033. X    }
  1034. X
  1035. X    /* let us know this is in progress */
  1036. X    mlwrite("[Building buffer list]");
  1037. X
  1038. X    /* disconect the current buffer */
  1039. X        if (--curbp->b_nwnd == 0) {             /* Last use.            */
  1040. X                curbp->b_dotp  = curwp->w_dotp;
  1041. X                curbp->b_doto  = curwp->w_doto;
  1042. X                curbp->b_markp = curwp->w_markp;
  1043. X                curbp->b_marko = curwp->w_marko;
  1044. X        }
  1045. X
  1046. X    /* connect the current window to this buffer */
  1047. X    curbp = bp;    /* make this buffer current in current window */
  1048. X    bp->b_mode = 0;        /* no modes active in binding list */
  1049. X    bp->b_nwnd++;        /* mark us as more in use */
  1050. X    wp = curwp;
  1051. X    wp->w_bufp = bp;
  1052. X    wp->w_linep = bp->b_linep;
  1053. X    wp->w_flag = WFHARD|WFFORCE;
  1054. X    wp->w_dotp = bp->b_dotp;
  1055. X    wp->w_doto = bp->b_doto;
  1056. X    wp->w_markp = NULL;
  1057. X    wp->w_marko = 0;
  1058. X
  1059. X    /* build the contents of this window, inserting it line by line */
  1060. X    nptr = &names[0];
  1061. X    while (nptr->n_func != NULL) {
  1062. X
  1063. X        /* add in the command name */
  1064. X        strcpy(outseq, nptr->n_name);
  1065. X        cpos = strlen(outseq);
  1066. X        
  1067. X        /* search down any keys bound to this */
  1068. X        ktp = &keytab[0];
  1069. X        while (ktp->k_fp != NULL) {
  1070. X            if (ktp->k_fp == nptr->n_func) {
  1071. X                /* padd out some spaces */
  1072. X                while (cpos < 25)
  1073. X                    outseq[cpos++] = ' ';
  1074. X
  1075. X                /* add in the command sequence */
  1076. X                cmdstr(ktp->k_code, &outseq[cpos]);
  1077. X                while (outseq[cpos] != 0)
  1078. X                    ++cpos;
  1079. X
  1080. X                /* and add it as a line into the buffer */
  1081. X                strp = &outseq[0];
  1082. X                while (*strp != 0)
  1083. X                    linsert(1, *strp++);
  1084. X                lnewline();
  1085. X
  1086. X                cpos = 0;    /* and clear the line */
  1087. X            }
  1088. X            ++ktp;
  1089. X        }
  1090. X
  1091. X        /* if no key was bound, we need to dump it anyway */
  1092. X        if (cpos > 0) {
  1093. X            outseq[cpos] = 0;
  1094. X            strp = &outseq[0];
  1095. X            while (*strp != 0)
  1096. X                linsert(1, *strp++);
  1097. X            lnewline();
  1098. X        }
  1099. X
  1100. X        /* and on to the next name */
  1101. X        ++nptr;
  1102. X    }
  1103. X
  1104. X    curwp->w_bufp->b_mode |= MDVIEW;/* put this buffer view mode */
  1105. X    curbp->b_flag &= ~BFCHG;    /* don't flag this as a change */
  1106. X    wp->w_dotp = lforw(bp->b_linep);/* back to the begining */
  1107. X    wp->w_doto = 0;
  1108. X    wp = wheadp;            /* and update ALL mode lines */
  1109. X    while (wp != NULL) {
  1110. X        wp->w_flag |= WFMODE;
  1111. X        wp = wp->w_wndp;
  1112. X    }
  1113. X    mlwrite("");    /* clear the mode line */
  1114. X    return(TRUE);
  1115. X}
  1116. X
  1117. Xgetckey(mflag)    /* get a command key sequence from the keyboard    */
  1118. X
  1119. Xint mflag;    /* going for a meta sequence? */
  1120. X
  1121. X{
  1122. X    register int c;        /* character fetched */
  1123. X    register char *tp;    /* pointer into the token */
  1124. X    char tok[NSTRING];    /* command incoming */
  1125. X
  1126. X    /* check to see if we are executing a command line */
  1127. X    if (clexec) {
  1128. X        nxtarg(tok);    /* get the next token */
  1129. X
  1130. X        /* parse it up */
  1131. X        tp = &tok[0];
  1132. X        c = 0;
  1133. X
  1134. X        /* first, the META prefix */
  1135. X        if (*tp == 'M' && *(tp+1) == '-') {
  1136. X            c = META;
  1137. X            tp += 2;
  1138. X        } else
  1139. X
  1140. X            /* next the function prefix */
  1141. X            if (*tp == 'F' && *(tp+1) == 'N') {
  1142. X                c |= SPEC;
  1143. X                tp += 2;
  1144. X            } else
  1145. X
  1146. X                /* control-x as well... */
  1147. X                if (*tp == '^' && *(tp+1) == 'X') {
  1148. X                    c |= CTLX;
  1149. X                    tp += 2;
  1150. X                }
  1151. X
  1152. X        /* a control char? */
  1153. X        if (*tp == '^' & *(tp+1) != 0) {
  1154. X            c |= CTRL;
  1155. X            ++tp;
  1156. X        }
  1157. X
  1158. X        /* make sure we are not lower case */
  1159. X        if (c >= 'a' && c <= 'z')
  1160. X            c -= 32;
  1161. X
  1162. X        /* the final sequence... */
  1163. X        c |= *tp;
  1164. X
  1165. X        return(c);
  1166. X    }
  1167. X
  1168. X    /* or the normal way */
  1169. X    if (mflag)
  1170. X        c = get1key();
  1171. X    else
  1172. X        c = getcmd();
  1173. X    return(c);
  1174. X}
  1175. X
  1176. X/* execute the startup file */
  1177. X
  1178. Xstartup(sfname)
  1179. X
  1180. Xchar *sfname;    /* name of startup file (null if default) */
  1181. X
  1182. X{
  1183. X    register int status;    /* status of I/O operations */
  1184. X    register int i;        /* index into help file names */
  1185. X    char fname[NSTRING];    /* buffer to construct file name in */
  1186. X    char *sfroot;        /* root of startup file name */
  1187. X
  1188. X#if    (MSDOS & (LATTICE | AZTEC | MSC)) | V7 | USG | BSD
  1189. X    char *homedir;        /* pointer to your home directory */
  1190. X    char *getenv();
  1191. X#endif
  1192. X
  1193. X    if (sfname[0] == 0)
  1194. X        sfroot = pathname[0];
  1195. X    else
  1196. X        sfroot = sfname;
  1197. X
  1198. X#if    (MSDOS & (LATTICE | AZTEC | MSC)) | V7 | USG | BSD
  1199. X    /* get the HOME from the environment */
  1200. X    if ((homedir = getenv("HOME")) != NULL) {
  1201. X        /* build the file name */
  1202. X        strcpy(fname, homedir);
  1203. X        strcat(fname, "/");
  1204. X        strcat(fname, sfroot);
  1205. X
  1206. X        /* and test it */
  1207. X        status = ffropen(fname);
  1208. X        if (status == FIOSUC) {
  1209. X            ffclose();
  1210. X            return(dofile(fname));
  1211. X        }
  1212. X    }
  1213. X#endif
  1214. X
  1215. X    /* search through the list of startup files */
  1216. X    for (i=2; i < NPNAMES; i++) {
  1217. X        strcpy(fname, pathname[i]);
  1218. X        strcat(fname, sfroot);
  1219. X        status = ffropen(fname);
  1220. X        if (status == FIOSUC)
  1221. X            break;
  1222. X    }
  1223. X
  1224. X    /* if it isn't around, don't sweat it */
  1225. X    if (status == FIOFNF)
  1226. X        return(TRUE);
  1227. X
  1228. X    ffclose();    /* close the file to prepare for to read it in */
  1229. X
  1230. X    return(dofile(fname));
  1231. X}
  1232. X
  1233. FRIDAY_NIGHT
  1234. echo extracting - buffer.c
  1235. sed 's/^X//' > buffer.c << 'FRIDAY_NIGHT'
  1236. X/*
  1237. X * Buffer management.
  1238. X * Some of the functions are internal,
  1239. X * and some are actually attached to user
  1240. X * keys. Like everyone else, they set hints
  1241. X * for the display system.
  1242. X */
  1243. X#include        <stdio.h>
  1244. X#include    "estruct.h"
  1245. X#include        "edef.h"
  1246. X
  1247. X/*
  1248. X * Attach a buffer to a window. The
  1249. X * values of dot and mark come from the buffer
  1250. X * if the use count is 0. Otherwise, they come
  1251. X * from some other window.
  1252. X */
  1253. Xusebuffer(f, n)
  1254. X{
  1255. X        register BUFFER *bp;
  1256. X        register int    s;
  1257. X        char            bufn[NBUFN];
  1258. X
  1259. X        if ((s=mlreply("Use buffer: ", bufn, NBUFN)) != TRUE)
  1260. X                return (s);
  1261. X        if ((bp=bfind(bufn, TRUE, 0)) == NULL)
  1262. X                return (FALSE);
  1263. X    return(swbuffer(bp));
  1264. X}
  1265. X
  1266. Xnextbuffer(f, n)    /* switch to the next buffer in the buffer list */
  1267. X
  1268. X{
  1269. X        register BUFFER *bp;
  1270. X
  1271. X    bp = curbp->b_bufp;
  1272. X    /* cycle through the buffers to find an eligable one */
  1273. X    while (bp == NULL || bp->b_flag & BFINVS) {
  1274. X        if (bp == NULL)
  1275. X            bp = bheadp;
  1276. X        else
  1277. X            bp = bp->b_bufp;
  1278. X    }
  1279. X    return(swbuffer(bp));
  1280. X}
  1281. X
  1282. Xswbuffer(bp)    /* make buffer BP current */
  1283. X
  1284. XBUFFER *bp;
  1285. X
  1286. X{
  1287. X        register WINDOW *wp;
  1288. X
  1289. X        if (--curbp->b_nwnd == 0) {             /* Last use.            */
  1290. X                curbp->b_dotp  = curwp->w_dotp;
  1291. X                curbp->b_doto  = curwp->w_doto;
  1292. X                curbp->b_markp = curwp->w_markp;
  1293. X                curbp->b_marko = curwp->w_marko;
  1294. X        }
  1295. X        curbp = bp;                             /* Switch.              */
  1296. X    if (curbp->b_active != TRUE) {        /* buffer not active yet*/
  1297. X        /* read it in and activate it */
  1298. X        readin(curbp->b_fname, TRUE);
  1299. X        curbp->b_dotp = lforw(curbp->b_linep);
  1300. X        curbp->b_doto = 0;
  1301. X        curbp->b_active = TRUE;
  1302. X    }
  1303. X        curwp->w_bufp  = bp;
  1304. X        curwp->w_linep = bp->b_linep;           /* For macros, ignored. */
  1305. X        curwp->w_flag |= WFMODE|WFFORCE|WFHARD; /* Quite nasty.         */
  1306. X        if (bp->b_nwnd++ == 0) {                /* First use.           */
  1307. X                curwp->w_dotp  = bp->b_dotp;
  1308. X                curwp->w_doto  = bp->b_doto;
  1309. X                curwp->w_markp = bp->b_markp;
  1310. X                curwp->w_marko = bp->b_marko;
  1311. X                return (TRUE);
  1312. X        }
  1313. X        wp = wheadp;                            /* Look for old.        */
  1314. X        while (wp != NULL) {
  1315. X                if (wp!=curwp && wp->w_bufp==bp) {
  1316. X                        curwp->w_dotp  = wp->w_dotp;
  1317. X                        curwp->w_doto  = wp->w_doto;
  1318. X                        curwp->w_markp = wp->w_markp;
  1319. X                        curwp->w_marko = wp->w_marko;
  1320. X                        break;
  1321. X                }
  1322. X                wp = wp->w_wndp;
  1323. X        }
  1324. X        return (TRUE);
  1325. X}
  1326. X
  1327. X/*
  1328. X * Dispose of a buffer, by name.
  1329. X * Ask for the name. Look it up (don't get too
  1330. X * upset if it isn't there at all!). Get quite upset
  1331. X * if the buffer is being displayed. Clear the buffer (ask
  1332. X * if the buffer has been changed). Then free the header
  1333. X * line and the buffer header. Bound to "C-X K".
  1334. X */
  1335. Xkillbuffer(f, n)
  1336. X
  1337. X{
  1338. X    register BUFFER *bp;
  1339. X        register int    s;
  1340. X        char bufn[NBUFN];
  1341. X
  1342. X        if ((s=mlreply("Kill buffer: ", bufn, NBUFN)) != TRUE)
  1343. X                return(s);
  1344. X        if ((bp=bfind(bufn, FALSE, 0)) == NULL) /* Easy if unknown.     */
  1345. X                return (TRUE);
  1346. X    return(zotbuf(bp));
  1347. X}
  1348. X
  1349. Xzotbuf(bp)    /* kill the buffer pointed to by bp */
  1350. X
  1351. Xregister BUFFER *bp;
  1352. X
  1353. X{
  1354. X        register BUFFER *bp1;
  1355. X        register BUFFER *bp2;
  1356. X        register int    s;
  1357. X
  1358. X        if (bp->b_nwnd != 0) {                  /* Error if on screen.  */
  1359. X                mlwrite("Buffer is being displayed");
  1360. X                return (FALSE);
  1361. X        }
  1362. X        if ((s=bclear(bp)) != TRUE)             /* Blow text away.      */
  1363. X                return (s);
  1364. X        free((char *) bp->b_linep);             /* Release header line. */
  1365. X        bp1 = NULL;                             /* Find the header.     */
  1366. X        bp2 = bheadp;
  1367. X        while (bp2 != bp) {
  1368. X                bp1 = bp2;
  1369. X                bp2 = bp2->b_bufp;
  1370. X        }
  1371. X        bp2 = bp2->b_bufp;                      /* Next one in chain.   */
  1372. X        if (bp1 == NULL)                        /* Unlink it.           */
  1373. X                bheadp = bp2;
  1374. X        else
  1375. X                bp1->b_bufp = bp2;
  1376. X        free((char *) bp);                      /* Release buffer block */
  1377. X        return (TRUE);
  1378. X}
  1379. X
  1380. Xnamebuffer(f,n)        /*    Rename the current buffer    */
  1381. X
  1382. Xint f, n;        /* default Flag & Numeric arg */
  1383. X
  1384. X{
  1385. X    register BUFFER *bp;    /* pointer to scan through all buffers */
  1386. X    char bufn[NBUFN];    /* buffer to hold buffer name */
  1387. X
  1388. X    /* prompt for and get the new buffer name */
  1389. Xask:    if (mlreply("Change buffer name to: ", bufn, NBUFN) != TRUE)
  1390. X        return(FALSE);
  1391. X
  1392. X    /* and check for duplicates */
  1393. X    bp = bheadp;
  1394. X    while (bp != NULL) {
  1395. X        if (bp != curbp) {
  1396. X            /* if the names the same */
  1397. X            if (strcmp(bufn, bp->b_bname) == 0)
  1398. X                goto ask;  /* try again */
  1399. X        }
  1400. X        bp = bp->b_bufp;    /* onward */
  1401. X    }
  1402. X
  1403. X    strcpy(curbp->b_bname, bufn);    /* copy buffer name to structure */
  1404. X    curwp->w_flag |= WFMODE;    /* make mode line replot */
  1405. X    mlerase();
  1406. X    return(TRUE);
  1407. X}
  1408. X
  1409. X/*
  1410. X * List all of the active
  1411. X * buffers. First update the special
  1412. X * buffer that holds the list. Next make
  1413. X * sure at least 1 window is displaying the
  1414. X * buffer list, splitting the screen if this
  1415. X * is what it takes. Lastly, repaint all of
  1416. X * the windows that are displaying the
  1417. X * list. Bound to "C-X C-B".
  1418. X */
  1419. Xlistbuffers(f, n)
  1420. X{
  1421. X        register WINDOW *wp;
  1422. X        register BUFFER *bp;
  1423. X        register int    s;
  1424. X
  1425. X        if ((s=makelist()) != TRUE)
  1426. X                return (s);
  1427. X        if (blistp->b_nwnd == 0) {              /* Not on screen yet.   */
  1428. X                if ((wp=wpopup()) == NULL)
  1429. X                        return (FALSE);
  1430. X                bp = wp->w_bufp;
  1431. X                if (--bp->b_nwnd == 0) {
  1432. X                        bp->b_dotp  = wp->w_dotp;
  1433. X                        bp->b_doto  = wp->w_doto;
  1434. X                        bp->b_markp = wp->w_markp;
  1435. X                        bp->b_marko = wp->w_marko;
  1436. X                }
  1437. X                wp->w_bufp  = blistp;
  1438. X                ++blistp->b_nwnd;
  1439. X        }
  1440. X        wp = wheadp;
  1441. X        while (wp != NULL) {
  1442. X                if (wp->w_bufp == blistp) {
  1443. X                        wp->w_linep = lforw(blistp->b_linep);
  1444. X                        wp->w_dotp  = lforw(blistp->b_linep);
  1445. X                        wp->w_doto  = 0;
  1446. X                        wp->w_markp = NULL;
  1447. X                        wp->w_marko = 0;
  1448. X                        wp->w_flag |= WFMODE|WFHARD;
  1449. X                }
  1450. X                wp = wp->w_wndp;
  1451. X        }
  1452. X        return (TRUE);
  1453. X}
  1454. X
  1455. X/*
  1456. X * This routine rebuilds the
  1457. X * text in the special secret buffer
  1458. X * that holds the buffer list. It is called
  1459. X * by the list buffers command. Return TRUE
  1460. X * if everything works. Return FALSE if there
  1461. X * is an error (if there is no memory).
  1462. X */
  1463. Xmakelist()
  1464. X{
  1465. X        register char   *cp1;
  1466. X        register char   *cp2;
  1467. X        register int    c;
  1468. X        register BUFFER *bp;
  1469. X        register LINE   *lp;
  1470. X        register int    s;
  1471. X    register int    i;
  1472. X        long    nbytes;        /* # of bytes in current buffer */
  1473. X        char            b[7+1];
  1474. X        char            line[128];
  1475. X
  1476. X        blistp->b_flag &= ~BFCHG;               /* Don't complain!      */
  1477. X        if ((s=bclear(blistp)) != TRUE)         /* Blow old text away   */
  1478. X                return (s);
  1479. X        strcpy(blistp->b_fname, "");
  1480. X        if (addline("AC MODES      Size Buffer        File") == FALSE
  1481. X        ||  addline("-- -----      ---- ------        ----") == FALSE)
  1482. X                return (FALSE);
  1483. X        bp = bheadp;                            /* For all buffers      */
  1484. X
  1485. X    /* build line to report global mode settings */
  1486. X    cp1 = &line[0];
  1487. X    *cp1++ = ' ';
  1488. X    *cp1++ = ' ';
  1489. X    *cp1++ = ' ';
  1490. X
  1491. X    /* output the mode codes */
  1492. X    for (i = 0; i < NUMMODES; i++)
  1493. X        if (gmode & (1 << i))
  1494. X            *cp1++ = modecode[i];
  1495. X        else
  1496. X            *cp1++ = '.';
  1497. X    strcpy(cp1, "         Global Modes");
  1498. X    if (addline(line) == FALSE)
  1499. X        return(FALSE);
  1500. X
  1501. X    /* output the list of buffers */
  1502. X        while (bp != NULL) {
  1503. X                if ((bp->b_flag&BFINVS) != 0) { /* Skip magic ones.     */
  1504. X                        bp = bp->b_bufp;
  1505. X                        continue;
  1506. X                }
  1507. X                cp1 = &line[0];                 /* Start at left edge   */
  1508. X
  1509. X        /* output status of ACTIVE flag (has the file been read in? */
  1510. X                if (bp->b_active == TRUE)    /* "@" if activated       */
  1511. X                        *cp1++ = '@';
  1512. X                else
  1513. X                        *cp1++ = ' ';
  1514. X
  1515. X        /* output status of changed flag */
  1516. X                if ((bp->b_flag&BFCHG) != 0)    /* "*" if changed       */
  1517. X                        *cp1++ = '*';
  1518. X                else
  1519. X                        *cp1++ = ' ';
  1520. X                *cp1++ = ' ';                   /* Gap.                 */
  1521. X
  1522. X        /* output the mode codes */
  1523. X        for (i = 0; i < NUMMODES; i++) {
  1524. X            if (bp->b_mode & (1 << i))
  1525. X                *cp1++ = modecode[i];
  1526. X            else
  1527. X                *cp1++ = '.';
  1528. X        }
  1529. X                *cp1++ = ' ';                   /* Gap.                 */
  1530. X                nbytes = 0L;                    /* Count bytes in buf.  */
  1531. X                lp = lforw(bp->b_linep);
  1532. X                while (lp != bp->b_linep) {
  1533. X                        nbytes += (long)llength(lp)+1L;
  1534. X                        lp = lforw(lp);
  1535. X                }
  1536. X                ltoa(b, 7, nbytes);             /* 6 digit buffer size. */
  1537. X                cp2 = &b[0];
  1538. X                while ((c = *cp2++) != 0)
  1539. X                        *cp1++ = c;
  1540. X                *cp1++ = ' ';                   /* Gap.                 */
  1541. X                cp2 = &bp->b_bname[0];          /* Buffer name          */
  1542. X                while ((c = *cp2++) != 0)
  1543. X                        *cp1++ = c;
  1544. X                cp2 = &bp->b_fname[0];          /* File name            */
  1545. X                if (*cp2 != 0) {
  1546. X                        while (cp1 < &line[2+1+5+1+6+1+NBUFN])
  1547. X                                *cp1++ = ' ';
  1548. X                        while ((c = *cp2++) != 0) {
  1549. X                                if (cp1 < &line[128-1])
  1550. X                                        *cp1++ = c;
  1551. X                        }
  1552. X                }
  1553. X                *cp1 = 0;                       /* Add to the buffer.   */
  1554. X                if (addline(line) == FALSE)
  1555. X                        return (FALSE);
  1556. X                bp = bp->b_bufp;
  1557. X        }
  1558. X        return (TRUE);                          /* All done             */
  1559. X}
  1560. X
  1561. Xltoa(buf, width, num)
  1562. X
  1563. Xchar   buf[];
  1564. Xint    width;
  1565. Xlong   num;
  1566. X
  1567. X{
  1568. X        buf[width] = 0;                         /* End of string.       */
  1569. X        while (num >= 10) {                     /* Conditional digits.  */
  1570. X                buf[--width] = (int)(num%10L) + '0';
  1571. X                num /= 10L;
  1572. X        }
  1573. X        buf[--width] = (int)num + '0';          /* Always 1 digit.      */
  1574. X        while (width != 0)                      /* Pad with blanks.     */
  1575. X                buf[--width] = ' ';
  1576. X}
  1577. X
  1578. X/*
  1579. X * The argument "text" points to
  1580. X * a string. Append this line to the
  1581. X * buffer list buffer. Handcraft the EOL
  1582. X * on the end. Return TRUE if it worked and
  1583. X * FALSE if you ran out of room.
  1584. X */
  1585. Xaddline(text)
  1586. Xchar    *text;
  1587. X{
  1588. X        register LINE   *lp;
  1589. X        register int    i;
  1590. X        register int    ntext;
  1591. X
  1592. X        ntext = strlen(text);
  1593. X        if ((lp=lalloc(ntext)) == NULL)
  1594. X                return (FALSE);
  1595. X        for (i=0; i<ntext; ++i)
  1596. X                lputc(lp, i, text[i]);
  1597. X        blistp->b_linep->l_bp->l_fp = lp;       /* Hook onto the end    */
  1598. X        lp->l_bp = blistp->b_linep->l_bp;
  1599. X        blistp->b_linep->l_bp = lp;
  1600. X        lp->l_fp = blistp->b_linep;
  1601. X        if (blistp->b_dotp == blistp->b_linep)  /* If "." is at the end */
  1602. X                blistp->b_dotp = lp;            /* move it to new line  */
  1603. X        return (TRUE);
  1604. X}
  1605. X
  1606. X/*
  1607. X * Look through the list of
  1608. X * buffers. Return TRUE if there
  1609. X * are any changed buffers. Buffers
  1610. X * that hold magic internal stuff are
  1611. X * not considered; who cares if the
  1612. X * list of buffer names is hacked.
  1613. X * Return FALSE if no buffers
  1614. X * have been changed.
  1615. X */
  1616. Xanycb()
  1617. X{
  1618. X        register BUFFER *bp;
  1619. X
  1620. X        bp = bheadp;
  1621. X        while (bp != NULL) {
  1622. X                if ((bp->b_flag&BFINVS)==0 && (bp->b_flag&BFCHG)!=0)
  1623. X                        return (TRUE);
  1624. X                bp = bp->b_bufp;
  1625. X        }
  1626. X        return (FALSE);
  1627. X}
  1628. X
  1629. X/*
  1630. X * Find a buffer, by name. Return a pointer
  1631. X * to the BUFFER structure associated with it.
  1632. X * If the buffer is not found
  1633. X * and the "cflag" is TRUE, create it. The "bflag" is
  1634. X * the settings for the flags in in buffer.
  1635. X */
  1636. XBUFFER  *
  1637. Xbfind(bname, cflag, bflag)
  1638. Xregister char   *bname;
  1639. X{
  1640. X        register BUFFER *bp;
  1641. X    register BUFFER *sb;    /* buffer to insert after */
  1642. X        register LINE   *lp;
  1643. X    char *malloc();
  1644. X
  1645. X        bp = bheadp;
  1646. X        while (bp != NULL) {
  1647. X                if (strcmp(bname, bp->b_bname) == 0)
  1648. X                        return (bp);
  1649. X                bp = bp->b_bufp;
  1650. X        }
  1651. X        if (cflag != FALSE) {
  1652. X                if ((bp=(BUFFER *)malloc(sizeof(BUFFER))) == NULL)
  1653. X                        return (NULL);
  1654. X                if ((lp=lalloc(0)) == NULL) {
  1655. X                        free((char *) bp);
  1656. X                        return (NULL);
  1657. X                }
  1658. X        /* find the place in the list to insert this buffer */
  1659. X        if (bheadp == NULL || strcmp(bheadp->b_bname, bname) > 0) {
  1660. X            /* insert at the begining */
  1661. X                    bp->b_bufp = bheadp;
  1662. X                    bheadp = bp;
  1663. X            } else {
  1664. X            sb = bheadp;
  1665. X            while (sb->b_bufp != NULL) {
  1666. X                if (strcmp(sb->b_bufp->b_bname, bname) > 0)
  1667. X                    break;
  1668. X                sb = sb->b_bufp;
  1669. X            }
  1670. X
  1671. X            /* and insert it */
  1672. X                   bp->b_bufp = sb->b_bufp;
  1673. X                sb->b_bufp = bp;
  1674. X               }
  1675. X
  1676. X        /* and set up the other buffer fields */
  1677. X        bp->b_active = TRUE;
  1678. X                bp->b_dotp  = lp;
  1679. X                bp->b_doto  = 0;
  1680. X                bp->b_markp = NULL;
  1681. X                bp->b_marko = 0;
  1682. X                bp->b_flag  = bflag;
  1683. X        bp->b_mode  = gmode;
  1684. X                bp->b_nwnd  = 0;
  1685. X                bp->b_linep = lp;
  1686. X                strcpy(bp->b_fname, "");
  1687. X                strcpy(bp->b_bname, bname);
  1688. X                lp->l_fp = lp;
  1689. X                lp->l_bp = lp;
  1690. X        }
  1691. X        return (bp);
  1692. X}
  1693. X
  1694. X/*
  1695. X * This routine blows away all of the text
  1696. X * in a buffer. If the buffer is marked as changed
  1697. X * then we ask if it is ok to blow it away; this is
  1698. X * to save the user the grief of losing text. The
  1699. X * window chain is nearly always wrong if this gets
  1700. X * called; the caller must arrange for the updates
  1701. X * that are required. Return TRUE if everything
  1702. X * looks good.
  1703. X */
  1704. Xbclear(bp)
  1705. Xregister BUFFER *bp;
  1706. X{
  1707. X        register LINE   *lp;
  1708. X        register int    s;
  1709. X
  1710. X        if ((bp->b_flag&BFINVS) == 0            /* Not scratch buffer.  */
  1711. X        && (bp->b_flag&BFCHG) != 0              /* Something changed    */
  1712. X        && (s=mlyesno("Discard changes")) != TRUE)
  1713. X                return (s);
  1714. X        bp->b_flag  &= ~BFCHG;                  /* Not changed          */
  1715. X        while ((lp=lforw(bp->b_linep)) != bp->b_linep)
  1716. X                lfree(lp);
  1717. X        bp->b_dotp  = bp->b_linep;              /* Fix "."              */
  1718. X        bp->b_doto  = 0;
  1719. X        bp->b_markp = NULL;                     /* Invalidate "mark"    */
  1720. X        bp->b_marko = 0;
  1721. X        return (TRUE);
  1722. X}
  1723. X
  1724. Xunmark(f, n)    /* unmark the current buffers change flag */
  1725. X
  1726. Xint f, n;    /* unused command arguments */
  1727. X
  1728. X{
  1729. X    curbp->b_flag &= ~BFCHG;
  1730. X    curwp->w_flag |= WFMODE;
  1731. X    return(TRUE);
  1732. X}
  1733. FRIDAY_NIGHT
  1734. echo es.1 completed!
  1735. : That's all folks!
  1736.  
  1737.  
  1738.