home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume1 / 8711 / microemacs-3.9 / 8 < prev    next >
Encoding:
Text File  |  1987-11-17  |  78.1 KB  |  2,465 lines

  1. Article 84 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 8 of 16)
  6. Message-ID: <5655@ncoast.UUCP>
  7. Date: 14 Nov 87 21:11:14 GMT
  8. Sender: allbery@ncoast.UUCP
  9. Lines: 2450
  10. Approved: allbery@ncoast.UUCP
  11. X-Archive: comp.sources.misc/microemacs-3.9/7
  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.8')
  17. # If you do not see the message
  18. #    `mes.8 completed!'
  19. # then the file was incomplete.
  20. echo extracting - line.c
  21. sed 's/^X//' > line.c << 'FRIDAY_NIGHT'
  22. X/*
  23. X * The functions in this file are a general set of line management utilities.
  24. X * They are the only routines that touch the text. They also touch the buffer
  25. X * and window structures, to make sure that the necessary updating gets done.
  26. X * There are routines in this file that handle the kill buffer too. It isn't
  27. X * here for any good reason.
  28. X *
  29. X * Note that this code only updates the dot and mark values in the window list.
  30. X * Since all the code acts on the current window, the buffer that we are
  31. X * editing must be being displayed, which means that "b_nwnd" is non zero,
  32. X * which means that the dot and mark values in the buffer headers are nonsense.
  33. X */
  34. X
  35. X#include    <stdio.h>
  36. X#include    "estruct.h"
  37. X#include    "edef.h"
  38. X
  39. XKILL *ykbuf;    /* ptr to current kill buffer chunk being yanked */
  40. Xint ykboff;    /* offset into that chunk */
  41. X
  42. X/*
  43. X * This routine allocates a block of memory large enough to hold a LINE
  44. X * containing "used" characters. The block is always rounded up a bit. Return
  45. X * a pointer to the new block, or NULL if there isn't any memory left. Print a
  46. X * message in the message line if no space.
  47. X */
  48. XLINE *lalloc(used)
  49. X
  50. Xregister int    used;
  51. X
  52. X{
  53. X    register LINE    *lp;
  54. X    register int    size;
  55. X    char *malloc();
  56. X
  57. X    size = (used+NBLOCK-1) & ~(NBLOCK-1);
  58. X    if (size == 0)                /* Assume that an empty */
  59. X        size = NBLOCK;            /* line is for type-in. */
  60. X    if ((lp = (LINE *) malloc(sizeof(LINE)+size)) == NULL) {
  61. X        mlwrite("[OUT OF MEMORY]");
  62. X        return (NULL);
  63. X    }
  64. X    lp->l_size = size;
  65. X    lp->l_used = used;
  66. X    return (lp);
  67. X}
  68. X
  69. X/*
  70. X * Delete line "lp". Fix all of the links that might point at it (they are
  71. X * moved to offset 0 of the next line. Unlink the line from whatever buffer it
  72. X * might be in. Release the memory. The buffers are updated too; the magic
  73. X * conditions described in the above comments don't hold here.
  74. X */
  75. Xlfree(lp)
  76. Xregister LINE    *lp;
  77. X{
  78. X    register BUFFER *bp;
  79. X    register WINDOW *wp;
  80. X
  81. X    wp = wheadp;
  82. X    while (wp != NULL) {
  83. X        if (wp->w_linep == lp)
  84. X            wp->w_linep = lp->l_fp;
  85. X        if (wp->w_dotp    == lp) {
  86. X            wp->w_dotp  = lp->l_fp;
  87. X            wp->w_doto  = 0;
  88. X        }
  89. X        if (wp->w_markp == lp) {
  90. X            wp->w_markp = lp->l_fp;
  91. X            wp->w_marko = 0;
  92. X        }
  93. X        wp = wp->w_wndp;
  94. X    }
  95. X    bp = bheadp;
  96. X    while (bp != NULL) {
  97. X        if (bp->b_nwnd == 0) {
  98. X            if (bp->b_dotp    == lp) {
  99. X                bp->b_dotp = lp->l_fp;
  100. X                bp->b_doto = 0;
  101. X            }
  102. X            if (bp->b_markp == lp) {
  103. X                bp->b_markp = lp->l_fp;
  104. X                bp->b_marko = 0;
  105. X            }
  106. X        }
  107. X        bp = bp->b_bufp;
  108. X    }
  109. X    lp->l_bp->l_fp = lp->l_fp;
  110. X    lp->l_fp->l_bp = lp->l_bp;
  111. X    free((char *) lp);
  112. X}
  113. X
  114. X/*
  115. X * This routine gets called when a character is changed in place in the current
  116. X * buffer. It updates all of the required flags in the buffer and window
  117. X * system. The flag used is passed as an argument; if the buffer is being
  118. X * displayed in more than 1 window we change EDIT t HARD. Set MODE if the
  119. X * mode line needs to be updated (the "*" has to be set).
  120. X */
  121. Xlchange(flag)
  122. Xregister int    flag;
  123. X{
  124. X    register WINDOW *wp;
  125. X
  126. X    if (curbp->b_nwnd != 1)         /* Ensure hard.     */
  127. X        flag = WFHARD;
  128. X    if ((curbp->b_flag&BFCHG) == 0) {    /* First change, so    */
  129. X        flag |= WFMODE;         /* update mode lines.    */
  130. X        curbp->b_flag |= BFCHG;
  131. X    }
  132. X    wp = wheadp;
  133. X    while (wp != NULL) {
  134. X        if (wp->w_bufp == curbp)
  135. X            wp->w_flag |= flag;
  136. X        wp = wp->w_wndp;
  137. X    }
  138. X}
  139. X
  140. Xinsspace(f, n)    /* insert spaces forward into text */
  141. X
  142. Xint f, n;    /* default flag and numeric argument */
  143. X
  144. X{
  145. X    linsert(n, ' ');
  146. X    backchar(f, n);
  147. X}
  148. X
  149. X/*
  150. X * linstr -- Insert a string at the current point
  151. X */
  152. X
  153. Xlinstr(instr)
  154. Xchar    *instr;
  155. X{
  156. X    register int status = TRUE;
  157. X    char tmpc;
  158. X
  159. X    if (instr != NULL)
  160. X        while ((tmpc = *instr) && status == TRUE) {
  161. X            status = (tmpc == '\n'? lnewline(): linsert(1, tmpc));
  162. X
  163. X            /* Insertion error? */
  164. X            if (status != TRUE) {
  165. X                mlwrite("%%Out of memory while inserting");
  166. X                break;
  167. X            }
  168. X            instr++;
  169. X        }
  170. X    return(status);
  171. X}
  172. X
  173. X/*
  174. X * Insert "n" copies of the character "c" at the current location of dot. In
  175. X * the easy case all that happens is the text is stored in the line. In the
  176. X * hard case, the line has to be reallocated. When the window list is updated,
  177. X * take special care; I screwed it up once. You always update dot in the
  178. X * current window. You update mark, and a dot in another window, if it is
  179. X * greater than the place where you did the insert. Return TRUE if all is
  180. X * well, and FALSE on errors.
  181. X */
  182. X
  183. Xlinsert(n, c)
  184. X{
  185. X    register char    *cp1;
  186. X    register char    *cp2;
  187. X    register LINE    *lp1;
  188. X    register LINE    *lp2;
  189. X    register LINE    *lp3;
  190. X    register int    doto;
  191. X    register int    i;
  192. X    register WINDOW *wp;
  193. X
  194. X    if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  195. X        return(rdonly());    /* we are in read only mode    */
  196. X    lchange(WFEDIT);
  197. X    lp1 = curwp->w_dotp;            /* Current line     */
  198. X    if (lp1 == curbp->b_linep) {        /* At the end: special    */
  199. X        if (curwp->w_doto != 0) {
  200. X            mlwrite("bug: linsert");
  201. X            return (FALSE);
  202. X        }
  203. X        if ((lp2=lalloc(n)) == NULL)    /* Allocate new line    */
  204. X            return (FALSE);
  205. X        lp3 = lp1->l_bp;        /* Previous line    */
  206. X        lp3->l_fp = lp2;        /* Link in        */
  207. X        lp2->l_fp = lp1;
  208. X        lp1->l_bp = lp2;
  209. X        lp2->l_bp = lp3;
  210. X        for (i=0; i<n; ++i)
  211. X            lp2->l_text[i] = c;
  212. X        curwp->w_dotp = lp2;
  213. X        curwp->w_doto = n;
  214. X        return (TRUE);
  215. X    }
  216. X    doto = curwp->w_doto;            /* Save for later.    */
  217. X    if (lp1->l_used+n > lp1->l_size) {    /* Hard: reallocate    */
  218. X        if ((lp2=lalloc(lp1->l_used+n)) == NULL)
  219. X            return (FALSE);
  220. X        cp1 = &lp1->l_text[0];
  221. X        cp2 = &lp2->l_text[0];
  222. X        while (cp1 != &lp1->l_text[doto])
  223. X            *cp2++ = *cp1++;
  224. X        cp2 += n;
  225. X        while (cp1 != &lp1->l_text[lp1->l_used])
  226. X            *cp2++ = *cp1++;
  227. X        lp1->l_bp->l_fp = lp2;
  228. X        lp2->l_fp = lp1->l_fp;
  229. X        lp1->l_fp->l_bp = lp2;
  230. X        lp2->l_bp = lp1->l_bp;
  231. X        free((char *) lp1);
  232. X    } else {                /* Easy: in place    */
  233. X        lp2 = lp1;            /* Pretend new line    */
  234. X        lp2->l_used += n;
  235. X        cp2 = &lp1->l_text[lp1->l_used];
  236. X        cp1 = cp2-n;
  237. X        while (cp1 != &lp1->l_text[doto])
  238. X            *--cp2 = *--cp1;
  239. X    }
  240. X    for (i=0; i<n; ++i)            /* Add the characters    */
  241. X        lp2->l_text[doto+i] = c;
  242. X    wp = wheadp;                /* Update windows    */
  243. X    while (wp != NULL) {
  244. X        if (wp->w_linep == lp1)
  245. X            wp->w_linep = lp2;
  246. X        if (wp->w_dotp == lp1) {
  247. X            wp->w_dotp = lp2;
  248. X            if (wp==curwp || wp->w_doto>doto)
  249. X                wp->w_doto += n;
  250. X        }
  251. X        if (wp->w_markp == lp1) {
  252. X            wp->w_markp = lp2;
  253. X            if (wp->w_marko > doto)
  254. X                wp->w_marko += n;
  255. X        }
  256. X        wp = wp->w_wndp;
  257. X    }
  258. X    return (TRUE);
  259. X}
  260. X
  261. X/*
  262. X * Overwrite a character into the current line at the current position
  263. X *
  264. X */
  265. X
  266. Xlowrite(c)
  267. X
  268. Xchar c;        /* character to overwrite on current position */
  269. X
  270. X{
  271. X    if (curwp->w_doto < curwp->w_dotp->l_used &&
  272. X        (lgetc(curwp->w_dotp, curwp->w_doto) != '\t' ||
  273. X         (curwp->w_doto) % 8 == 7))
  274. X            ldelete(1L, FALSE);
  275. X    return(linsert(1, c));
  276. X}
  277. X
  278. X/*
  279. X * lover -- Overwrite a string at the current point
  280. X */
  281. X
  282. Xlover(ostr)
  283. X
  284. Xchar    *ostr;
  285. X
  286. X{
  287. X    register int status = TRUE;
  288. X    char tmpc;
  289. X
  290. X    if (ostr != NULL)
  291. X        while ((tmpc = *ostr) && status == TRUE) {
  292. X            status = (tmpc == '\n'? lnewline(): lowrite(tmpc));
  293. X
  294. X            /* Insertion error? */
  295. X            if (status != TRUE) {
  296. X                mlwrite("%%Out of memory while overwriting");
  297. X                break;
  298. X            }
  299. X            ostr++;
  300. X        }
  301. X    return(status);
  302. X}
  303. X
  304. X/*
  305. X * Insert a newline into the buffer at the current location of dot in the
  306. X * current window. The funny ass-backwards way it does things is not a botch;
  307. X * it just makes the last line in the file not a special case. Return TRUE if
  308. X * everything works out and FALSE on error (memory allocation failure). The
  309. X * update of dot and mark is a bit easier then in the above case, because the
  310. X * split forces more updating.
  311. X */
  312. Xlnewline()
  313. X{
  314. X    register char    *cp1;
  315. X    register char    *cp2;
  316. X    register LINE    *lp1;
  317. X    register LINE    *lp2;
  318. X    register int    doto;
  319. X    register WINDOW *wp;
  320. X
  321. X    if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  322. X        return(rdonly());    /* we are in read only mode    */
  323. X    lchange(WFHARD);
  324. X    lp1  = curwp->w_dotp;            /* Get the address and    */
  325. X    doto = curwp->w_doto;            /* offset of "."    */
  326. X    if ((lp2=lalloc(doto)) == NULL)     /* New first half line    */
  327. X        return (FALSE);
  328. X    cp1 = &lp1->l_text[0];            /* Shuffle text around    */
  329. X    cp2 = &lp2->l_text[0];
  330. X    while (cp1 != &lp1->l_text[doto])
  331. X        *cp2++ = *cp1++;
  332. X    cp2 = &lp1->l_text[0];
  333. X    while (cp1 != &lp1->l_text[lp1->l_used])
  334. X        *cp2++ = *cp1++;
  335. X    lp1->l_used -= doto;
  336. X    lp2->l_bp = lp1->l_bp;
  337. X    lp1->l_bp = lp2;
  338. X    lp2->l_bp->l_fp = lp2;
  339. X    lp2->l_fp = lp1;
  340. X    wp = wheadp;                /* Windows        */
  341. X    while (wp != NULL) {
  342. X        if (wp->w_linep == lp1)
  343. X            wp->w_linep = lp2;
  344. X        if (wp->w_dotp == lp1) {
  345. X            if (wp->w_doto < doto)
  346. X                wp->w_dotp = lp2;
  347. X            else
  348. X                wp->w_doto -= doto;
  349. X        }
  350. X        if (wp->w_markp == lp1) {
  351. X            if (wp->w_marko < doto)
  352. X                wp->w_markp = lp2;
  353. X            else
  354. X                wp->w_marko -= doto;
  355. X        }
  356. X        wp = wp->w_wndp;
  357. X    }
  358. X    return (TRUE);
  359. X}
  360. X
  361. X/*
  362. X * This function deletes "n" bytes, starting at dot. It understands how do deal
  363. X * with end of lines, etc. It returns TRUE if all of the characters were
  364. X * deleted, and FALSE if they were not (because dot ran into the end of the
  365. X * buffer. The "kflag" is TRUE if the text should be put in the kill buffer.
  366. X */
  367. Xldelete(n, kflag)
  368. X
  369. Xlong n;     /* # of chars to delete */
  370. Xint kflag;    /* put killed text in kill buffer flag */
  371. X
  372. X{
  373. X    register char    *cp1;
  374. X    register char    *cp2;
  375. X    register LINE    *dotp;
  376. X    register int    doto;
  377. X    register int    chunk;
  378. X    register WINDOW *wp;
  379. X
  380. X    if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  381. X        return(rdonly());    /* we are in read only mode    */
  382. X    while (n != 0) {
  383. X        dotp = curwp->w_dotp;
  384. X        doto = curwp->w_doto;
  385. X        if (dotp == curbp->b_linep)    /* Hit end of buffer.    */
  386. X            return (FALSE);
  387. X        chunk = dotp->l_used-doto;    /* Size of chunk.    */
  388. X        if (chunk > n)
  389. X            chunk = n;
  390. X        if (chunk == 0) {        /* End of line, merge.    */
  391. X            lchange(WFHARD);
  392. X            if (ldelnewline() == FALSE
  393. X            || (kflag!=FALSE && kinsert('\n')==FALSE))
  394. X                return (FALSE);
  395. X            --n;
  396. X            continue;
  397. X        }
  398. X        lchange(WFEDIT);
  399. X        cp1 = &dotp->l_text[doto];    /* Scrunch text.    */
  400. X        cp2 = cp1 + chunk;
  401. X        if (kflag != FALSE) {        /* Kill?        */
  402. X            while (cp1 != cp2) {
  403. X                if (kinsert(*cp1) == FALSE)
  404. X                    return (FALSE);
  405. X                ++cp1;
  406. X            }
  407. X            cp1 = &dotp->l_text[doto];
  408. X        }
  409. X        while (cp2 != &dotp->l_text[dotp->l_used])
  410. X            *cp1++ = *cp2++;
  411. X        dotp->l_used -= chunk;
  412. X        wp = wheadp;            /* Fix windows        */
  413. X        while (wp != NULL) {
  414. X            if (wp->w_dotp==dotp && wp->w_doto>=doto) {
  415. X                wp->w_doto -= chunk;
  416. X                if (wp->w_doto < doto)
  417. X                    wp->w_doto = doto;
  418. X            }
  419. X            if (wp->w_markp==dotp && wp->w_marko>=doto) {
  420. X                wp->w_marko -= chunk;
  421. X                if (wp->w_marko < doto)
  422. X                    wp->w_marko = doto;
  423. X            }
  424. X            wp = wp->w_wndp;
  425. X        }
  426. X        n -= chunk;
  427. X    }
  428. X    return (TRUE);
  429. X}
  430. X
  431. X/* getctext:    grab and return a string with the text of
  432. X        the current line
  433. X*/
  434. X
  435. Xchar *getctext()
  436. X
  437. X{
  438. X    register LINE *lp;    /* line to copy */
  439. X    register int size;    /* length of line to return */
  440. X    register char *sp;    /* string pointer into line */
  441. X    register char *dp;    /* string pointer into returned line */
  442. X    char rline[NSTRING];    /* line to return */
  443. X
  444. X    /* find the contents of the current line and its length */
  445. X    lp = curwp->w_dotp;
  446. X    sp = lp->l_text;
  447. X    size = lp->l_used;
  448. X    if (size >= NSTRING)
  449. X        size = NSTRING - 1;
  450. X
  451. X    /* copy it across */
  452. X    dp = rline;
  453. X    while (size--)
  454. X        *dp++ = *sp++;
  455. X    *dp = 0;
  456. X    return(rline);
  457. X}
  458. X
  459. X/* putctext:    replace the current line with the passed in text    */
  460. X
  461. Xputctext(iline)
  462. X
  463. Xchar *iline;    /* contents of new line */
  464. X
  465. X{
  466. X    register int status;
  467. X
  468. X    /* delete the current line */
  469. X    curwp->w_doto = 0;    /* starting at the beginning of the line */
  470. X    if ((status = killtext(TRUE, 1)) != TRUE)
  471. X        return(status);
  472. X
  473. X    /* insert the new line */
  474. X    if ((status = linstr(iline)) != TRUE)
  475. X        return(status);
  476. X    status = lnewline();
  477. X    backline(TRUE, 1);
  478. X    return(status);
  479. X}
  480. X
  481. X/*
  482. X * Delete a newline. Join the current line with the next line. If the next line
  483. X * is the magic header line always return TRUE; merging the last line with the
  484. X * header line can be thought of as always being a successful operation, even
  485. X * if nothing is done, and this makes the kill buffer work "right". Easy cases
  486. X * can be done by shuffling data around. Hard cases require that lines be moved
  487. X * about in memory. Return FALSE on error and TRUE if all looks ok. Called by
  488. X * "ldelete" only.
  489. X */
  490. Xldelnewline()
  491. X{
  492. X    register char    *cp1;
  493. X    register char    *cp2;
  494. X    register LINE    *lp1;
  495. X    register LINE    *lp2;
  496. X    register LINE    *lp3;
  497. X    register WINDOW *wp;
  498. X
  499. X    if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  500. X        return(rdonly());    /* we are in read only mode    */
  501. X    lp1 = curwp->w_dotp;
  502. X    lp2 = lp1->l_fp;
  503. X    if (lp2 == curbp->b_linep) {        /* At the buffer end.    */
  504. X        if (lp1->l_used == 0)        /* Blank line.        */
  505. X            lfree(lp1);
  506. X        return (TRUE);
  507. X    }
  508. X    if (lp2->l_used <= lp1->l_size-lp1->l_used) {
  509. X        cp1 = &lp1->l_text[lp1->l_used];
  510. X        cp2 = &lp2->l_text[0];
  511. X        while (cp2 != &lp2->l_text[lp2->l_used])
  512. X            *cp1++ = *cp2++;
  513. X        wp = wheadp;
  514. X        while (wp != NULL) {
  515. X            if (wp->w_linep == lp2)
  516. X                wp->w_linep = lp1;
  517. X            if (wp->w_dotp == lp2) {
  518. X                wp->w_dotp  = lp1;
  519. X                wp->w_doto += lp1->l_used;
  520. X            }
  521. X            if (wp->w_markp == lp2) {
  522. X                wp->w_markp  = lp1;
  523. X                wp->w_marko += lp1->l_used;
  524. X            }
  525. X            wp = wp->w_wndp;
  526. X        }
  527. X        lp1->l_used += lp2->l_used;
  528. X        lp1->l_fp = lp2->l_fp;
  529. X        lp2->l_fp->l_bp = lp1;
  530. X        free((char *) lp2);
  531. X        return (TRUE);
  532. X    }
  533. X    if ((lp3=lalloc(lp1->l_used+lp2->l_used)) == NULL)
  534. X        return (FALSE);
  535. X    cp1 = &lp1->l_text[0];
  536. X    cp2 = &lp3->l_text[0];
  537. X    while (cp1 != &lp1->l_text[lp1->l_used])
  538. X        *cp2++ = *cp1++;
  539. X    cp1 = &lp2->l_text[0];
  540. X    while (cp1 != &lp2->l_text[lp2->l_used])
  541. X        *cp2++ = *cp1++;
  542. X    lp1->l_bp->l_fp = lp3;
  543. X    lp3->l_fp = lp2->l_fp;
  544. X    lp2->l_fp->l_bp = lp3;
  545. X    lp3->l_bp = lp1->l_bp;
  546. X    wp = wheadp;
  547. X    while (wp != NULL) {
  548. X        if (wp->w_linep==lp1 || wp->w_linep==lp2)
  549. X            wp->w_linep = lp3;
  550. X        if (wp->w_dotp == lp1)
  551. X            wp->w_dotp  = lp3;
  552. X        else if (wp->w_dotp == lp2) {
  553. X            wp->w_dotp  = lp3;
  554. X            wp->w_doto += lp1->l_used;
  555. X        }
  556. X        if (wp->w_markp == lp1)
  557. X            wp->w_markp  = lp3;
  558. X        else if (wp->w_markp == lp2) {
  559. X            wp->w_markp  = lp3;
  560. X            wp->w_marko += lp1->l_used;
  561. X        }
  562. X        wp = wp->w_wndp;
  563. X    }
  564. X    free((char *) lp1);
  565. X    free((char *) lp2);
  566. X    return (TRUE);
  567. X}
  568. X
  569. X/*
  570. X * Delete all of the text saved in the kill buffer. Called by commands when a
  571. X * new kill context is being created. The kill buffer array is released, just
  572. X * in case the buffer has grown to immense size. No errors.
  573. X */
  574. Xkdelete()
  575. X{
  576. X    KILL *kp;    /* ptr to scan kill buffer chunk list */
  577. X
  578. X    if (kbufh != NULL) {
  579. X
  580. X        /* first, delete all the chunks */
  581. X        kbufp = kbufh;
  582. X        while (kbufp != NULL) {
  583. X            kp = kbufp->d_next;
  584. X            free(kbufp);
  585. X            kbufp = kp;
  586. X        }
  587. X
  588. X        /* and reset all the kill buffer pointers */
  589. X        kbufh = kbufp = NULL;
  590. X        kused = KBLOCK;             
  591. X    }
  592. X}
  593. X
  594. X/*
  595. X * Insert a character to the kill buffer, allocating new chunks as needed.
  596. X * Return TRUE if all is well, and FALSE on errors.
  597. X */
  598. X
  599. Xkinsert(c)
  600. X
  601. Xint c;        /* character to insert in the kill buffer */
  602. X
  603. X{
  604. X    KILL *nchunk;    /* ptr to newly malloced chunk */
  605. X
  606. X    /* check to see if we need a new chunk */
  607. X    if (kused >= KBLOCK) {
  608. X        if ((nchunk = (KILL *)malloc(sizeof(KILL))) == NULL)
  609. X            return(FALSE);
  610. X        if (kbufh == NULL)    /* set head ptr if first time */
  611. X            kbufh = nchunk;
  612. X        if (kbufp != NULL)    /* point the current to this new one */
  613. X            kbufp->d_next = nchunk;
  614. X        kbufp = nchunk;
  615. X        kbufp->d_next = NULL;
  616. X        kused = 0;
  617. X    }
  618. X
  619. X    /* and now insert the character */
  620. X    kbufp->d_chunk[kused++] = c;
  621. X    return(TRUE);
  622. X}
  623. X
  624. X/*
  625. X * Yank text back from the kill buffer. This is really easy. All of the work
  626. X * is done by the standard insert routines. All you do is run the loop, and
  627. X * check for errors. Bound to "C-Y".
  628. X */
  629. Xyank(f, n)
  630. X{
  631. X    register int    c;
  632. X    register int    i;
  633. X    register char    *sp;    /* pointer into string to insert */
  634. X    KILL *kp;        /* pointer into kill buffer */
  635. X
  636. X    if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  637. X        return(rdonly());    /* we are in read only mode    */
  638. X    if (n < 0)
  639. X        return (FALSE);
  640. X    /* make sure there is something to yank */
  641. X    if (kbufh == NULL)
  642. X        return(TRUE);        /* not an error, just nothing */
  643. X
  644. X    /* for each time.... */
  645. X    while (n--) {
  646. X        kp = kbufh;
  647. X        while (kp != NULL) {
  648. X            if (kp->d_next == NULL)
  649. X                i = kused;
  650. X            else
  651. X                i = KBLOCK;
  652. X            sp = kp->d_chunk;
  653. X            while (i--) {
  654. X                if ((c = *sp++) == '\n') {
  655. X                    if (lnewline() == FALSE)
  656. X                        return (FALSE);
  657. X                } else {
  658. X                    if (linsert(1, c) == FALSE)
  659. X                        return (FALSE);
  660. X                }
  661. X            }
  662. X            kp = kp->d_next;
  663. X        }
  664. X    }
  665. X    return (TRUE);
  666. X}
  667. FRIDAY_NIGHT
  668. echo extracting - lock.c
  669. sed 's/^X//' > lock.c << 'FRIDAY_NIGHT'
  670. X/*    LOCK:    File locking command routines for MicroEMACS
  671. X        written by Daniel Lawrence
  672. X                                */
  673. X
  674. X#include <stdio.h>
  675. X#include "estruct.h"
  676. X#include "edef.h"
  677. X
  678. X#if    FILOCK
  679. X#if    BSD
  680. X#include <sys/errno.h>
  681. X
  682. Xextern int sys_nerr;        /* number of system error messages defined */
  683. Xextern char *sys_errlist[];    /* list of message texts */
  684. Xextern int errno;        /* current error */
  685. X
  686. Xchar *lname[NLOCKS];    /* names of all locked files */
  687. Xint numlocks;        /* # of current locks active */
  688. X
  689. X/* lockchk:    check a file for locking and add it to the list */
  690. X
  691. Xlockchk(fname)
  692. X
  693. Xchar *fname;    /* file to check for a lock */
  694. X
  695. X{
  696. X    register int i;        /* loop indexes */
  697. X    register int status;    /* return status */
  698. X    char *undolock();
  699. X
  700. X    /* check to see if that file is already locked here */
  701. X    if (numlocks > 0)
  702. X        for (i=0; i < numlocks; ++i)
  703. X            if (strcmp(fname, lname[i]) == 0)
  704. X                return(TRUE);
  705. X
  706. X    /* if we have a full locking table, bitch and leave */
  707. X    if (numlocks == NLOCKS) {
  708. X        mlwrite("LOCK ERROR: Lock table full");
  709. X        return(ABORT);
  710. X    }
  711. X
  712. X    /* next, try to lock it */
  713. X    status = lock(fname);
  714. X    if (status == ABORT)    /* file is locked, no override */
  715. X        return(ABORT);
  716. X    if (status == FALSE)    /* locked, overriden, dont add to table */
  717. X        return(TRUE);
  718. X
  719. X    /* we have now locked it, add it to our table */
  720. X    lname[++numlocks - 1] = (char *)malloc(strlen(fname) + 1);
  721. X    if (lname[numlocks - 1] == NULL) {    /* malloc failure */
  722. X        undolock(fname);        /* free the lock */
  723. X        mlwrite("Cannot lock, out of memory");
  724. X        --numlocks;
  725. X        return(ABORT);
  726. X    }
  727. X
  728. X    /* everthing is cool, add it to the table */
  729. X    strcpy(lname[numlocks-1], fname);
  730. X    return(TRUE);
  731. X}
  732. X
  733. X/*    lockrel:    release all the file locks so others may edit */
  734. X
  735. Xlockrel()
  736. X
  737. X{
  738. X    register int i;        /* loop index */
  739. X    register int status;    /* status of locks */
  740. X    register int s;        /* status of one unlock */
  741. X
  742. X    status = TRUE;
  743. X    if (numlocks > 0)
  744. X        for (i=0; i < numlocks; ++i) {
  745. X            if ((s = unlock(lname[i])) != TRUE)
  746. X                status = s;
  747. X            free(lname[i]);
  748. X        }
  749. X    numlocks = 0;
  750. X    return(status);
  751. X}
  752. X
  753. X/* lock:    Check and lock a file from access by others
  754. X        returns    TRUE = files was not locked and now is
  755. X            FALSE = file was locked and overridden
  756. X            ABORT = file was locked, abort command
  757. X*/
  758. X
  759. Xlock(fname)
  760. X
  761. Xchar *fname;    /* file name to lock */
  762. X
  763. X{
  764. X    register char *locker;    /* lock error message */
  765. X    register int status;    /* return status */
  766. X    char msg[NSTRING];    /* message string */
  767. X    char *dolock();
  768. X
  769. X    /* attempt to lock the file */
  770. X    locker = dolock(fname);
  771. X    if (locker == NULL)    /* we win */
  772. X        return(TRUE);
  773. X
  774. X    /* file failed...abort */
  775. X    if (strncmp(locker, "LOCK", 4) == 0) {
  776. X        lckerror(locker);
  777. X        return(ABORT);
  778. X    }
  779. X
  780. X    /* someone else has it....override? */
  781. X    strcpy(msg, "File in use by ");
  782. X    strcat(msg, locker);
  783. X    strcat(msg, ", overide?");
  784. X    status = mlyesno(msg);        /* ask them */
  785. X    if (status == TRUE)
  786. X        return(FALSE);
  787. X    else
  788. X        return(ABORT);
  789. X}
  790. X
  791. X/*    unlock:    Unlock a file
  792. X        this only warns the user if it fails
  793. X                            */
  794. X
  795. Xunlock(fname)
  796. X
  797. Xchar *fname;    /* file to unlock */
  798. X
  799. X{
  800. X    register char *locker;    /* undolock return string */
  801. X    char *undolock();
  802. X
  803. X    /* unclock and return */
  804. X    locker = undolock(fname);
  805. X    if (locker == NULL)
  806. X        return(TRUE);
  807. X
  808. X    /* report the error and come back */
  809. X    lckerror(locker);
  810. X    return(FALSE);
  811. X}
  812. X
  813. Xlckerror(errstr)    /* report a lock error */
  814. X
  815. Xchar *errstr;        /* lock error string to print out */
  816. X
  817. X{
  818. X    char obuf[NSTRING];    /* output buffer for error message */
  819. X
  820. X    strcpy(obuf, errstr);
  821. X    strcat(obuf, " - ");
  822. X    if (errno < sys_nerr)
  823. X        strcat(obuf, sys_errlist[errno]);
  824. X    else
  825. X        strcat(obuf, "[can not get system error message]");
  826. X    mlwrite(obuf);
  827. X}
  828. X#endif
  829. X#else
  830. Xlckhello()    /* dummy function */
  831. X{
  832. X}
  833. X#endif
  834. FRIDAY_NIGHT
  835. echo extracting - main.c
  836. sed 's/^X//' > main.c << 'FRIDAY_NIGHT'
  837. X/*
  838. X *    MicroEMACS 3.9
  839. X *             written by Dave G. Conroy.
  840. X *            substatially modified by Daniel M. Lawrence
  841. X *
  842. X *    (C)opyright 1987 by Daniel M. Lawrence
  843. X *    MicroEMACS 3.9 can be copied and distributed freely for any
  844. X *    non-commercial purposes. MicroEMACS 3.9 can only be incorporated
  845. X *    into commercial software with the permission of the current author.
  846. X *
  847. X * This file contains the main driving routine, and some keyboard processing
  848. X * code, for the MicroEMACS screen editor.
  849. X *
  850. X * REVISION HISTORY:
  851. X *
  852. X * 1.0  Steve Wilhite, 30-Nov-85
  853. X *      - Removed the old LK201 and VT100 logic. Added code to support the
  854. X *        DEC Rainbow keyboard (which is a LK201 layout) using the the Level
  855. X *        1 Console In ROM INT. See "rainbow.h" for the function key defs
  856. X *      Steve Wilhite, 1-Dec-85
  857. X *      - massive cleanup on code in display.c and search.c
  858. X *
  859. X * 2.0  George Jones, 12-Dec-85
  860. X *      - Ported to Amiga.
  861. X *
  862. X * 3.0  Daniel Lawrence, 29-Dec-85
  863. X *      - rebound keys/added new fast buffered I/O for AMIGA
  864. X *    - added META- repeat commands
  865. X *    - added reposition default to center screen (yeah!)
  866. X *    - changed exit with modified buffers message
  867. X *    - made filesave tell us what it is doing
  868. X *    - changed search string entry to terminate with <ESC>
  869. X *      so we can use <NL> in search/replace strings
  870. X *    - updated version number in mode line to 3.0
  871. X *    12-Jan-86
  872. X *    - Added code to reconize the search/replace functions
  873. X *    - Added code to perform search/replace & query functions
  874. X *    14-Jan-86
  875. X *    - moved search logic to separate function in search.c
  876. X *    - added replace and query replace functions
  877. X *    - separated out control key expansions to be used by others in search.c
  878. X *    15-Jan-86
  879. X *    - changed "visiting" to finding
  880. X *    - changed yes/no responses to not need return
  881. X *    - cleaned up various messages
  882. X *    16-jan-86
  883. X *    - fixed spurious spawn message in MSDOS
  884. X *    - added ^X-S synonym to save command
  885. X *    - moved escape to shell to ^X-C
  886. X *    21-jan-86
  887. X *    - added code to suspend shell under BSD
  888. X *    22-jan-86
  889. X *    - added function key support (SPEC) under MSDOS
  890. X *    - Abort now prints [Aborted] on message line
  891. X *    23-jan-86
  892. X *    - Added modes and commands to set/unset them
  893. X *    24-jan-86
  894. X *    - Added Goto Line command
  895. X *    - added Rename Buffer command
  896. X *    28-jan-86
  897. X *    - added goto beginning and end of paragraph commands (META-P/META-N)
  898. X *    - re-wrote kdelete to use realloc. Gained MUCH speed here when
  899. X *      doing large wipes on both UNIX and MSDOS. Changed kill buffer
  900. X *      allocation block size from 256 bytes to 1 k
  901. X *    29-jan-86
  902. X *    - moved extern function declarations to efunc.h
  903. X *    - made name[] name binding table
  904. X *    30-jan-86
  905. X *    - fixed Previous/Next paragraph command not to wrap around EOF
  906. X *    - added Fill Paragraph command (META-Q)
  907. X *    4-feb-86
  908. X *    - added code to properly display long lines, scrolling them right
  909. X *      to left
  910. X *    5-feb-85
  911. X *    - rewrote code to right/left scroll...much better
  912. X *    - added shifted arrow keys on IBMPC
  913. X *    6-feb-85
  914. X *    - add option to allow forward-word to jump to beginning of
  915. X *      next word instead of end of current one. This is different from
  916. X *      other emacs' but can be configured off in estruct.h
  917. X *    - added VIEW mode to allow a buffer to be read only
  918. X *       (-v switch on command line will activate this)
  919. X *    - changed quick exit to write out ALL changed buffers!!!
  920. X *      MAKE SURE YOU KNOW THIS WHEN META-Zing
  921. X *    10-feb-86
  922. X *    - added handling of lines longer than allowed on file read in
  923. X *      (they wrap on additional lines)
  924. X *    - made having space clear the message line and NOT insert itself
  925. X *      a configuration option in ed.h
  926. X *    11-feb-86
  927. X *    - added Describe-command and Help commands.
  928. X *    13-feb-86
  929. X *    - added View file command (^X ^V) and finished HELP command
  930. X *    14-feb-86
  931. X *    - added option to let main loop skip update if type ahead commands
  932. X *       are queued up
  933. X *    16-feb-86
  934. X *    - added Insert File command
  935. X *    17-feb-86
  936. X *    - added scroll next window up/down commands
  937. X *    18-feb-86
  938. X *    - added CMODE indentation
  939. X *    - re-arranged header files to standardize extern and global
  940. X *      definitions
  941. X *    - changed version number to 3.2
  942. X *    - added numeric arguments to search, reverse search and
  943. X *      search and replace
  944. X *    24-feb-86
  945. X *    - added Bind To Key function (^C for now) to allow the user
  946. X *      to change his command keys
  947. X *    - added Unbind key function (M-^C for now)
  948. X *    - added execute named command to execute unbound commands (M-X)
  949. X *    - added describe bindings command (not bound)
  950. X *    - changed version number to 3.3
  951. X *    25-feb-86
  952. X *    - scrapped CERROR mode (too many compilers)
  953. X *    - added EXACT mode for case sensitive searchers
  954. X *    26-feb-86
  955. X *    - added command completion on execute named command and
  956. X *      all routined grabbing a command name
  957. X *    - adding execute-command-line command and its support functions
  958. X *      (in preparation for sourcing files)
  959. X *    - added Execute Buffer command
  960. X *    27-feb-86
  961. X *    - added execute(source) file command and added code to automatically
  962. X *      execute emacs.rc (or .emacsrc on UNIX) before initial read in
  963. X *    - changed version number to 3.4
  964. X *    4-mar-86
  965. X *    - changed word delete to be consistant with word move (it gets
  966. X *      rid of the inter word space now) This is configurable with the
  967. X *      NFWORD symbol in estruct.h
  968. X *    - added B_ACTIVE entry to the buffer table. Let emacs read multiple
  969. X *      file names from the command line and only read them in as needed
  970. X *    5-mar-85
  971. X *    - rewrote command line parser to get rid of my patchy code
  972. X *    - changed version number to 3.5
  973. X *    1-apr-86
  974. X *    - added support for Aztec C 3.20e under MSDOS
  975. X *    - fixed bug in mlwrite on ADM3's and their ilk under V7
  976. X *    - added insertion of pounds in column one under CMODE
  977. X *    - changed version number to 3.6
  978. X *    3-apr-86
  979. X *    - added next-buffer command (^X-X)
  980. X *    5-apr-86
  981. X *    - added kill paragraph command (M-^W)
  982. X *    - changed fill-paragraph to leave 2 spaces after a period at the
  983. X *      end of a word.
  984. X *    - added OVERWRITE mode
  985. X *    7-apr-86
  986. X *    - fixed overwrite mode to handle tabs
  987. X *    8-apr-86
  988. X *    - added add/delete global mode (<ESC>M & <ESC> ^M) commands
  989. X *    9-apr-86
  990. X *    - added insert space command
  991. X *    - moved bindings around        ^C    insert space
  992. X *                    M-K    bind-to-key
  993. X *                    INSERT    insert space
  994. X *                    DELETE    forwdel
  995. X *    - added hunt forward and hunt reverse commands
  996. X *    10-apr-86
  997. X *    - fixed bug in DOBUF with non-terminated command string
  998. X *    15-apr-86
  999. X *    - fixed tab expansion bug in DISPLAY which hung the AMIGA
  1000. X *      (sent in by Dawn Banks)
  1001. X *    - fixed curcol problen if forwline/backline during keyboard
  1002. X *      macro execution (sent in by Ernst Christen)
  1003. X *    - added AMIGA function/cursor key support
  1004. X *    - fixed nonterminating <NL> replacement bug
  1005. X *    - fixed word wrapping problems
  1006. X *    16-apr-86
  1007. X *    - updated documentation and froze development for 3.6 net release
  1008. X *    23-apr-86    version 3.6a
  1009. X *    - added foreground and background colors. Setable with the
  1010. X *      add mode commands for the moment
  1011. X *    24-apr-86
  1012. X *    - added command to pipe CLI output to a buffer
  1013. X *    25-apr-86
  1014. X *    - added Dana Hoggatt's code to replace Lattice's sick system()
  1015. X *      function. Now we no longer care what the switchar is.
  1016. X *    - cleaned up the positioning on several of the spawing commands
  1017. X *    26-apr-86
  1018. X *    - added an output flush in vttidy(). Unix really appreciates this.
  1019. X *    - added filter-buffer (^X#) command to send a buffer through
  1020. X *      a DOS filter
  1021. X *    - made automatic CMODE on .c and .h file compilation dependant
  1022. X *      in estruct.h
  1023. X *    1-may-86
  1024. X *    - optimized some code in update(). It certainly need a lot more.
  1025. X *    - added Aztec profiling capabilities. These are conditional on
  1026. X *      the APROF symbol in estruct.h
  1027. X *    2-may-86
  1028. X *    - added (u)ndo command in query-replace. undoes last repalce.
  1029. X *    6-may-86
  1030. X *    - re-organized and wrote the update() function in display.c
  1031. X *      Now my color hacks are in the right places and the code can be
  1032. X *      understood.
  1033. X *    [Released version 3.6f for BETA test sites]
  1034. X *    8-may-86
  1035. X *    - fixed bug in new display routine to wrap cursor on extended
  1036. X *      lines at the right time
  1037. X *    - modified the buffer-position command to give reasonable info
  1038. X *    9-may-86
  1039. X *    - improved the word wrap algorithm as not to discard non-space
  1040. X *      delimiters. The backscan now looks for white space rather than
  1041. X *      !inword().
  1042. X *    [Released version 3.6g to Krannert]
  1043. X *    10-may-86
  1044. X *    - Added IBMPC.C an IBM-PC specific display driver. This makes paging
  1045. X *      4-6 times faster. Also made some conditional changes to DISPLAY.C
  1046. X *      to eliminate the pscreen[] if using the PC driver.
  1047. X *    [changed version number to 3.6i]
  1048. X *    12-may-86
  1049. X *    - added delete-window (^X 0) command to dispose of a single window
  1050. X *    - fixed problem with multiple prefixes from a command line which
  1051. X *      was reported by John Gamble
  1052. X *    14-may-86
  1053. X *    - Added Aztec support for the IBMPC display driver. Had to
  1054. X *      readjust some includes and defines for this.
  1055. X *    - fixed bug in delete-window.
  1056. X *    - fixed some bizarre behavior with the cursor after coming back
  1057. X *      from spawn calls.
  1058. X *    [changed version number to 3.7 freezing development for net release]
  1059. X *    15-may-86
  1060. X *    - (that didn't last long...) Added execute-macro-(1 thru 20) commands
  1061. X *      to execute macro buffers (named "[Macro nn]")
  1062. X *    - changed BFTEMP to BFINVS and cleaned up treatment of invisible
  1063. X *      buffers.
  1064. X *    16-may-86
  1065. X *    - added store-macro (unbound) to store any executed command lines to
  1066. X *      macro buffer.
  1067. X *    - added clear-message-line (unbound) command to do just that
  1068. X *    - added resize-window command to change a window's size to the
  1069. X *      specified argument
  1070. X *    - improved help's logic not to re-read the file if it was already
  1071. X *      in a buffer
  1072. X *    - added MAGIC mode to all structures and command tables, but the
  1073. X *      regular expression code that John Gamble is writing is not ready.
  1074. X *    18-may-86
  1075. X *    - added interactive prompt requests in command line execution (i.e.
  1076. X *      while executing a macro, a parameter starting with an at sign (@)
  1077. X *      causes emacs to prompt with the rest of the parameter and return
  1078. X *      the resulting input as the value of the parameter).
  1079. X *    - added arguments to split-current-window to force the cursor into
  1080. X *      the upper or lower window.
  1081. X *    20-may-86
  1082. X *    - added support for the Microsoft C compiler as per the changes
  1083. X *      sent in by Oliver Sharp
  1084. X *    - made some upgrades and fixes for VMS sent in by Guy Streeter
  1085. X *    21-may-86
  1086. X *    - fixed an Aztec bug in ttgetc by clearing the upper byte
  1087. X *    - fixed buf in CMODE with #preprocesser input (bug fix submitted by
  1088. X *      Willis of unknown path)
  1089. X *    - added support of alternative startup file ( @<filename> ) in
  1090. X *      the command line
  1091. X *    - added ^Q quoting in interactive input (mlreplyt()).
  1092. X *    - added re-binding of meta-prefix and ctlx-prefix
  1093. X *    22-may-86
  1094. X *    - reorganized getkey routines to make more sense and let prefix
  1095. X *      binding work properly.
  1096. X *    23-may-86
  1097. X *    - checked new code on BSD4.2 and made a few fixes
  1098. X *    - added optional fence matching while in CMODE
  1099. X *    - added goto and search command line arguments by Mike Spitzer
  1100. X *    26-may-86
  1101. X *    - added parameter fetching from buffers
  1102. X *    27-may-86
  1103. X *    - fixed some HP150 bugs......
  1104. X *    31-may-86
  1105. X *    - Added Wang PC keyboard support from modifications by
  1106. X *      Sid Shapiro @ Wang Institute
  1107. X *    - Fixed some reverse video bugs with code submitted by Peter Chubb
  1108. X *    - Fixed bug in nextbuffer reported by Dave Forslund
  1109. X *    - added system V support (USG) from Linwood Varney
  1110. X *    2-jun-86
  1111. X *    - changed defines to just define one Unix define (for example,
  1112. X *      just define BSD for Unix BSD 4.2)
  1113. X *    - Added Incremental search functions written by D. R. Banks
  1114. X *      in file ISEARCH.C
  1115. X *    - added insert-string (unbound) command to help the macro
  1116. X *      language out.
  1117. X *    - added unmark-buffer (M-~) command to turn off the current buffers
  1118. X *      change flag
  1119. X *    - fixed nxtarg to truncate strings longer than asked for max length
  1120. X *    4-jun-86
  1121. X *    - added special characters in command line tokens. Tilde (~) is
  1122. X *      the special lead-in character for "nrtb".
  1123. X *    - Fixed bad ifdef in Aztec code so it could look at HOME dir
  1124. X *      for startup, help, and emacs.rc files
  1125. X *    6-jun-86
  1126. X *    - make delete word commands clear the kill buffer if not after another
  1127. X *      kill command
  1128. X *    11-jun-86
  1129. X *    - made ~@ in string arguments pass as char(192) to nxtarg() so one can
  1130. X *      quote @ at the beginning of string arguments
  1131. X *    - changed buffer size vars in listbuffers() to long (for big files)
  1132. X *    - re-wrote buffer-position command to be much faster
  1133. X *    12-jun-86
  1134. X *    - added count-words (M-^C) command to count the words/chars and
  1135. X *      lines in a region
  1136. X *    - changed regions so they could be larger than 65535 (short ->
  1137. X *      long in the REGION structure)
  1138. X *    - changed ldelete() and all callers to use a long size. The kill
  1139. X *      buffer will still have a problem >65535 that can not be solved
  1140. X *      until I restructure it.
  1141. X *    - grouped paragraph commands and word count together under symbol
  1142. X *      WORDPRO to allow them to be conditionally made (or not)
  1143. X *    13-jun-86
  1144. X *    - re-wrote kill buffer routines again. Now they support an unlimited
  1145. X *      size kill buffer, and are (in theory) faster.
  1146. X *    - changed delete-next-word (M-D) to not eat the newline after a word,
  1147. X *      instead it checks and eats a newline at the cursor.
  1148. X *    17-jun-86
  1149. X *    - added numeric argument to next/previous-window to access the nth
  1150. X *      window from the top/bottom
  1151. X *    - added support for the Data General 10 MSDOS machine
  1152. X *    - added save-window (unbound) and restore-window (unbound) commands
  1153. X *      for the use of the menu script. Save-window remembers which window
  1154. X *      is current, and restore-window returns the cursor to that window.
  1155. X *    20-jun-86
  1156. X *    - fixed a bug with the fence matching locking up near the beginning
  1157. X *      of a buffer
  1158. X *    - added argument to update to selectively force a complete update
  1159. X *    - added update-screen (unbound) command so macros can force a
  1160. X *      screen update
  1161. X *    21-jun-86
  1162. X *    - rearranged token() and nxtarg() calls so that command names and
  1163. X *      repeat counts could also be prompted and fetched from buffers
  1164. X *      [this broke later with the exec re-write....]
  1165. X *    - added write-message (unbound) command to write out a message
  1166. X *      on the message line (for macros)
  1167. X *    - changed ifdef's so that color modes are recognized as legal in
  1168. X *      b/w version, and simply do nothing (allowing us to use the same
  1169. X *      script files)
  1170. X *    [Released version 3.7 on July 1 to the net and elswhere]
  1171. X *    2-jul-86
  1172. X *    - Changed search string terminator to always be the meta character
  1173. X *      even if it is rebound.
  1174. X *    3-jul-86
  1175. X *    - removed extra calls to set color in startup code. This caused the
  1176. X *      original current window to always be the global colors.
  1177. X *    7-jul-86
  1178. X *    - Fixed bugs in mlreplyt() to work properly with all terminators
  1179. X *      including control and spec characters
  1180. X *    22-jul-86
  1181. X *    - fixed replaces() so that it will return FALSE properly on the
  1182. X *      input of the replacement string.
  1183. X *    - added a definition for FAILED as a return type.....
  1184. X *    - changed version number to 3.7b
  1185. X *    23-jul-86
  1186. X *    - fixed o -> 0 problem in TERMIO.C
  1187. X *    - made ^U universal-argument re-bindable
  1188. X *    - wrote atoi() for systems (like Aztec) where it acts strangely
  1189. X *    - changed version number to 3.7c
  1190. X *    25-jul-86
  1191. X *    - make ^G abort-command rebindable
  1192. X *    29-jul-86
  1193. X *    - added HP110 Portable Computer support
  1194. X *    - changed version number to 3.7d
  1195. X *    30-jul-86
  1196. X *    - Fixed a couple of errors in the new VMS code as pointer
  1197. X *      out by Ken Shacklford
  1198. X *    - split terminal open/close routines into screen and keyboard
  1199. X *      open/close routines
  1200. X *    - closed the keyboard during all disk I/O so that OS errors
  1201. X *      can be respoded to correctly (especially on the HP150)
  1202. X *    - changed version number to 3.7e
  1203. X *    31-jul-86
  1204. X *    - added label-function-key (unbound) command under symbol FLABEL
  1205. X *      (primarily for the HP150)
  1206. X *    4-aug-86
  1207. X *    - added fixes for Microsoft C as suggested by ihnp4!ihuxm!gmd1
  1208. X *        <<remember to fix [list] deletion bug as reported
  1209. X *          by craig@hp-pcd>>
  1210. X *    8-aug-86
  1211. X *    - fixed beginning misspelling error everywhere
  1212. X *    - fixed some more MSC errors
  1213. X *    - changed version number to 3.7g
  1214. X *    20-aug-86
  1215. X *    - fixed CMODE .h scanning bug
  1216. X *    - changed version number to 3.7h
  1217. X *    30-aug-86
  1218. X *    - fixed killing renamed [list] buffer (it can't) as submitted
  1219. X *      by James Aldridge
  1220. X *    - Added code to allow multiple lines to display during
  1221. X *      vertical retrace
  1222. X *      [total disaster....yanked it back out]
  1223. X *    9-sep-86
  1224. X *    - added M-A (apropos) command to list commands containing a substring.
  1225. X *    - fixed an inefficiency in the display update code submitted
  1226. X *      by William W. Carlson (wwc@pur-ee)
  1227. X *    10-sep-86
  1228. X *    - added Dana Hoggatt's code for encryption and spliced it into the
  1229. X *      proper commands. CRYPT mode now triggers encryption.
  1230. X *    - added -k flag to allow encryption key (no spaces) in command line
  1231. X *    14-sep-86
  1232. X *    - added missing lastflag/thisflag processing to docmd()
  1233. X *    - changed version to 3.7i and froze for partial release via mail
  1234. X *      and BBS
  1235. X *    05-oct-86
  1236. X *    - changed some strcpys in MAIN.C to strncpys as suggested by John
  1237. X *      Gamble
  1238. X *    - replaces SEARCH.C and ISEARCH.C with versions modified by
  1239. X *      John Gamble
  1240. X *    10-oct-86
  1241. X *    - removed references to lflick....it just won't work that way.
  1242. X *    - removed defines LAT2 and LAT3...the code no longer is Lattice
  1243. X *      version dependant.
  1244. X *    14-oct-86
  1245. X *    - changed spawn so that it will not not pause if executed from
  1246. X *      a command line
  1247. X *    15-oct-86
  1248. X *    - added argument concatination (+) to the macro parsing
  1249. X *    - added [] as fence pairs
  1250. X *    16-oct-86
  1251. X *    - rewrote all macro line parsing routines and rearranged the
  1252. X *      mlreply code. Saved 6K!!! Have blazed the path for expanding
  1253. X *      the command language.
  1254. X *    17-oct-86
  1255. X *    - added new keyboard macro routines (plus a new level to the
  1256. X *      input character function)
  1257. X *    22-oct-86
  1258. X *    - improved EGA cursor problems
  1259. X *    - added -r (restricted) switch to command line for BBS use
  1260. X *    06-nov-86
  1261. X *    - fixed terminator declarations from char to int in getarg() and
  1262. X *      nxtarg() in EXEC.C as pointed out by John Gamble
  1263. X *    07-nov-86
  1264. X *    - made wordrap() user callable as wrap-word (M-FNW) and changed
  1265. X *      the getckey() routine so that illegal keystrokes (too many
  1266. X *      prefixes set) could be used for internal bindings. When word
  1267. X *      wrap conditions are met, the keystroke M-FNW is executed. Added
  1268. X *      word wrap check/call to newline().
  1269. X *    11-nov-86
  1270. X *    - added and checked support for Mark Williams C 86
  1271. X *    12-nov-86
  1272. X *    - added goto-matching-fence (M-^F) command to jump to a matching
  1273. X *      fence "({[]})" or beep if there is none. This can reframe the
  1274. X *      screen.
  1275. X *    - added code and structure elements to support change-screen-size
  1276. X *      command (M-^S) to change the number of lines being used by
  1277. X *      MicroEMACS.
  1278. X *    15-nov-86
  1279. X *    - finished debugging change-screen-size
  1280. X *    17-nov-86
  1281. X *    - Incorporated in James Turner's modifications for the Atari ST
  1282. X *        23-sep-86
  1283. X *        - added support for the Atari ST line of computers (jmt)
  1284. X *          - added a '\r' to the end of each line on output and strip
  1285. X *            it on input for the SHOW function from the desktop
  1286. X *          - added 3 new mode functions (HIREZ, MEDREZ, and LOREZ);
  1287. X *            chgrez routine in TERM structure; and MULTREZ define in
  1288. X *            ESTRUCT.H to handle multiple screen resolutions
  1289. X *    [note....ST still not running under Lattice yet...]
  1290. X *    25-nov-86
  1291. X *    - Made the filter-buffer (^X-#) command not work on VIEW mode
  1292. X *      buffers
  1293. X *    - Made the quick-exit (M-Z) command throw out a newline after
  1294. X *      each message so they could be seen.
  1295. X *    26-nov-86
  1296. X *    - fixed a couple of bugs in change-screen-size (M-^S) command
  1297. X *    - changed file read behavior on long lines and last lines
  1298. X *      with no newline (it no longer throws the partial line out)
  1299. X *    - [as suggested by Dave Tweten] Made adding a ^Z to the end
  1300. X *      of an output file under MSDOS configurable under the
  1301. X *      CTRL-Z symbol in ESTRUCT.H
  1302. X *    - [Dave Tweten] Spawn will look up the "TMP" environment variable
  1303. X *      for use during various pipeing commands.
  1304. X *    - [Dave Tweten] changed pipe command under MSDOS to use '>>'
  1305. X *      instead of '>'
  1306. X *    04-dec-86
  1307. X *    - moved processing of '@' and '#' so that they can be outside
  1308. X *      the quotes in an argument, and added hooks to process '%' for
  1309. X *      environment and user variables.
  1310. X *    - modified IBMPC.C to sense the graphics adapter (CGA and MONO)
  1311. X *      at runtime to cut down on the number of versions.
  1312. X *    05-dec-86
  1313. X *    - changed macro directive character to "!" instead of "$" (see
  1314. X *      below) and fixed the standard .rc file to comply.
  1315. X *    - added code to interpret environment variables ($vars). Added
  1316. X *      hooks for built in functions (&func). So, to recap:
  1317. X *
  1318. X *        @<string>    prompt and return a string from the user
  1319. X *        #<buffer name>    get the next line from a buffer and advance
  1320. X *        %<var>        get user variable <var>
  1321. X *        $<evar>        get environment variable <evar>
  1322. X *        &<func>        evaluate function <func>
  1323. X *
  1324. X *    - allowed repeat counts to be any of the above
  1325. X *    - added code to allow insert-string (unbound) to use its
  1326. X *      repeat count properly
  1327. X *    - added set (^X-A) command to set variables. Only works on
  1328. X *      environmental vars yet.
  1329. X *    9-dec-86
  1330. X *    - added some code for user defined variables...more to come
  1331. X *    - added options for malloc() memory pool tracking
  1332. X *    - preliminary user variables (%) working
  1333. X *    - changed terminal calls to macro's (to prepare for the new
  1334. X *      terminal drivers)
  1335. X *    15-dec-86
  1336. X *    - changed previous-line (^P) and next-line (^N) to return a
  1337. X *      FALSE at the end or beginning of the file so repeated
  1338. X *      macros involving them terminate properly!
  1339. X *    - added code for $CURCOL and $CURLINE
  1340. X *    20-dec-86
  1341. X *    - set (^X-A) now works with all vars
  1342. X *    - added some new functions
  1343. X *          &ADD &SUB &TIMES &DIV &MOD &NEG &CAT
  1344. X *    - once again rearranged functions to control macro execution. Did
  1345. X *      away with getarg()
  1346. X *    23-dec-86
  1347. X *    - added string functions
  1348. X *          &LEFt &RIGht &MID
  1349. X *    31-dec-86
  1350. X *    - added many logical functions
  1351. X *          &NOT &EQUal &LESs &GREater
  1352. X *    - added string functions
  1353. X *          &SEQual &SLEss &SGReater
  1354. X *    - added variable indirection with &INDirect
  1355. X *    - made fixes to allow recursive macro executions
  1356. X *      (improved speed during macro execution as well)
  1357. X *    3-jan-87
  1358. X *    - added $FLICKER to control flicker supression
  1359. X *    - made spawn commands restricted
  1360. X *    - cleaned up lots of unintentional int<->char problems
  1361. X *    4-jan-87
  1362. X *    - Fixed broken pipe-command (^X-@) command under MSDOS
  1363. X *    - added !IF  !ELSE  !ENDIF  directives and changed the
  1364. X *      name of !END to !ENDM....real slick stuff
  1365. X *    5-jan-87
  1366. X *    - quick-exit (M-Z) aborts on any filewrite errors
  1367. X *    8-jan-87
  1368. X *    - debugged a lot of the new directive and evaluation code.
  1369. X *      BEWARE of stack space overflows! (increasing stack to
  1370. X *      16K under MSDOS)
  1371. X *    - removed non-standard DEC Rainbow keyboard support...let someone
  1372. X *      PLEASE implement this in the standard manner using key bindings
  1373. X *      and send the results to me.
  1374. X *    - added change-screen-width () command and $CURWIDTH variable
  1375. X *    11-jan-87
  1376. X *    - fixed an incredibly deeply buried bug in vtputc and combined
  1377. X *      it with vtpute (saving about 200 bytes!)
  1378. X *    16-jan-87
  1379. X *    - added code to handle controlling multiple screen resolutions...
  1380. X *      allowed the IBM-PC driver to force Mono or CGA modes.
  1381. X *    - added current buffer name and filename variables
  1382. X *      $cbufname and $cfname
  1383. X *    18-jan-87
  1384. X *    - added $sres variable to control screen resolution
  1385. X *    - added $debug variable to control macro debugging code (no longer
  1386. X *      is this activated by GLOBAL spell mode)
  1387. X *    - fixed bug in -g command line option
  1388. X *    - Released Version 3.8 to BBSNET
  1389. X *    21-jan-87
  1390. X *    - added $status variable to record return status of last command
  1391. X *    2-feb-87
  1392. X *    - added ATARI 1040 support...runs in all three modes right now
  1393. X *    - added $palette var with palette value in it
  1394. X *    - undefined "register" in BIND.C and INPUT.C for ST520 & LATTICE
  1395. X *      to get around a nasty Lattice bug
  1396. X *    4-feb-87
  1397. X *    - added, debugged code for switching all 1040ST color modes, added
  1398. X *      code for HIGH monochrome mode as well, DENSE still pending
  1399. X *    5-feb-87
  1400. X *    - with John Gamble, found and corrected the infamous bad matching
  1401. X *      fence problems.
  1402. X *    - added error return check in various add/delete mode commands
  1403. X *    10-feb-87
  1404. X *    - re-arrange code in docmd() so that labels are stored in
  1405. X *      macro buffers
  1406. X *    - fixed !RETURN to only return if (execlevel == 0) [If we are
  1407. X *      currently executing]
  1408. X *    14-feb-87
  1409. X *    - added to outp() calls in the EGA driver to fix a bug in the BIOS
  1410. X *    - adding code for 1040ST 40 line DENSE mode (not complete)
  1411. X *    25-feb-87
  1412. X *    - added auto-save "ASAVE" mode....variables $asave and $acount
  1413. X *      control the frequency of saving and count until next save
  1414. X *    - added &and and &or as functions for logical anding and oring
  1415. X *    - added string length &LEN, upper and lower case string funtions
  1416. X *      &LOWER and &UPPER
  1417. X *    27-feb-87
  1418. X *    - added $lastkey   last keystroke struck and
  1419. X *            $curchar    character under cursor
  1420. X *    28-feb-87
  1421. X *    - added code for trim-line (^X^T) command and table entries
  1422. X *      for the entab-line (^X^E) and detab-line (^X^D) commands.
  1423. X *      These are conditional on AEDIT (Advanced editing) in estruct.h
  1424. X *    18-mar-87
  1425. X *    - finished above three commands
  1426. X *    - added $version environment variable to return the current
  1427. X *      MicroEMACS version number
  1428. X *    - added $discmd emvironment variable. This is a logical flag that
  1429. X *      indicates if emacs should be echoing commands on the command line.
  1430. X *      real useful in order to stop flashing macros and .rc files
  1431. X *    - added $progname environment variable. this always returns the
  1432. X *      string "MicroEMACS". OEM's should change this so that macros can
  1433. X *      tell if they are running on an unmodified emacs or not.
  1434. X *    - fixed a minor bug in the CGA/MONO detection routine in IBMPC.C
  1435. X *    20-mar-87
  1436. X *    - integrated EGAPC.C into IBMPC.C and eliminated the file. Now an
  1437. X *      EGA user can switch from EGA to CGA modes at will
  1438. X *    - A LOT of little fixes and corrections sent in by John Ruply
  1439. X *    25-mar-87
  1440. X *    - Fixed buffer variables so they will work when referencing the
  1441. X *      current buffer
  1442. X *    26-mar-87
  1443. X *    - Fixed atoi() to be more reasonable. trailing whitespace ignored,
  1444. X *      only one leading sign, no non-digits allowed after the sign.
  1445. X *    - fixed buffer variables to go from the point to the end of
  1446. X *      line.
  1447. X *    28-mar-87
  1448. X *    - fixed bugs with 8 bit chars as submited by Jari Salminen
  1449. X *    - replace AZTEC/MSDOS agetc() with a1getc() which won't strip
  1450. X *      the high order bit
  1451. X *    30-mar-87
  1452. X *    - changed list-buffers (^X^B) so that with any argument, it will
  1453. X *      also list the normally invisable buffers
  1454. X *    - added store-procedure and execute-procedure/run (M-^E)
  1455. X *      commands to store and execute named procedures.
  1456. X *    31-mar-87
  1457. X *    - Fixed infinite loop in ^X-X command (when [LIST] is the
  1458. X *      only buffer left) as pointed out by John Maline
  1459. X *    - made filenames in getfile() always lower case as pointed
  1460. X *      out by John Maline
  1461. X *    2-apr-87
  1462. X *    - Fixed buffer variables so they would work on non-current displayed
  1463. X *      buffers. They should now work with ALL buffers....
  1464. X *    3-apr-87
  1465. X *    - Yanked AZTEC profiling code....not very useful
  1466. X *    - Modified IBMPC driver so it will not start in EGA mode
  1467. X *    - allow the next-buffer (^X-X) command to have a preceding
  1468. X *      non-negative argument.
  1469. X *    14-apr-87
  1470. X *    - added John Gamble's modified search.c. The code has cut apx
  1471. X *      200-300 bytes off the executable.
  1472. X *    - added the &RND function to generate a random integer between
  1473. X *      1 and its arguments value. Also $SEED is availible as the
  1474. X *      random number seed.
  1475. X *    - changed the -k command line switch so if there is no argument,
  1476. X *      it will prompt for one when the file is read
  1477. X *    15-apr-87
  1478. X *    - added 20 bytes of buffer in getval()'s local argument alloc so
  1479. X *      when it returns a value, it has enough stack space to do at least
  1480. X *      one strcpy() before stomping on the returned value. ALWAYS call
  1481. X *      getval() ONLY from within a strcpy() call.
  1482. X *    - made $curcol return a 1 based value instead of a zero based one.
  1483. X *      [changed this back later for 3.8o   it was simply wrong.....]
  1484. X *    16-apr-87
  1485. X *    - re-wrote strncpy() for AZTEC & MSDOS so it null terminates the
  1486. X *      string.
  1487. X *    - changed pipe() to pipecmd() to avoid conflicts with various
  1488. X *      UNIX systems
  1489. X *    24-apr-87
  1490. X *    - changed open parameters on AMIGA window open to 0/0/640/200
  1491. X *    [Froze and released v3.8i via BBS net]
  1492. X *    14-may-87
  1493. X *    - added nop (M-FNC) that gets called on every command loop
  1494. X *    - added $wline, returns and sets # lines in current window
  1495. X *    - added $cwline, returns and set current line within window
  1496. X *    - added $target, returns/sets target for line moves
  1497. X *    - added $search, returns/sets default search string
  1498. X *    - added $replace, returns/sets default replace string
  1499. X *    - added $match, returns last matched string in magic search
  1500. X *    29-may-87
  1501. X *    - rewrote word deletes to not kill trailing non-whitespace after
  1502. X *      the last word. Also a zero argument will cause it to just delete
  1503. X *      the word and nothing else.
  1504. X *    - more fixes for the search pattern environment variables
  1505. X *    30-may-87
  1506. X *    - forced all windows to redraw on a width change
  1507. X *    2-jun-87
  1508. X *    - forced clear-message-line to overide $discmd
  1509. X *    - added mlforce() routine and call it in clear-message-line,
  1510. X *      write-message and when $debug is TRUE
  1511. X *    - recoded the startup sequence in main()....Much Better...
  1512. X *    4-jun-87
  1513. X *    - forced interactive arguments ( @"question" ) to ALWAYS be echoed
  1514. X *      regardless of the setting of $discmd.
  1515. X *    7-jun-87
  1516. X *    - started adding support for Turbo C under MSDOS
  1517. X *    11-jun-87
  1518. X *    - words now include ONLY upper/lower case alphas and digits
  1519. X *    - fixed some more bugs with the startup..(ORed in the global modes)
  1520. X *    - took more limits off the self-insert list....
  1521. X *    16-jun-87
  1522. X *    - macro debugging now displays the name of the current macro.
  1523. X *    - fixed a problem in expandp() in search.c that kept high-byte
  1524. X *      characters from working in search strings
  1525. X *    18-jun-87
  1526. X *    - added &sindex <str1> <str2> function which searches for string 2
  1527. X *      within string 1
  1528. X *    [released verion 3.8o internally]
  1529. X *    19-jun-87
  1530. X *    - added $cmode and $gmode to return and set the mode of the
  1531. X *      current buffer and the global mode
  1532. X *    - separated findvar() out from setvar() so it could be used in
  1533. X *      the !LOOP directive (which got canned....read on)
  1534. X *    - %No such variable message now types the name of the offending
  1535. X *      variable
  1536. X *    22-jun-87
  1537. X *    - fixed startup bug when editing the startup file
  1538. X *    - added the !LOOP <var> <label> directive
  1539. X *    26-jun-87
  1540. X *    - dumped !LOOP......added !WHILE. This needed and caused a vaste
  1541. X *      reorginization in exec.c which mainly involved moving all the
  1542. X *      directive handling from docmd() to dobuf(), in the process
  1543. X *      getting rid of a lot of junk and making the result smaller
  1544. X *      than it started.....(yea!)
  1545. X *    - added $tpause to control the fence flashing time in CMODE.
  1546. X *      The value is machine dependant, but you can multiply the
  1547. X *      original in macros to stay machine independant. (as
  1548. X *      suggested by Baron O.A. Grey)
  1549. X *    - added hook to execute M-FNR (null) during a file read, after
  1550. X *      the name is set and right before the file is read. Took out
  1551. X *      any auto-CMODE code, as this is now handled with a macro.
  1552. X *      (also suggested by Baron O.A. Grey)
  1553. X *    - Added Baron O.A. Grey's SYSTEM V typeahead() code...I hope
  1554. X *      this works....if you check this out, drop me a line.
  1555. X *    - Added new variable $pending, returns a logical telling if
  1556. X *      a typed ahead character is pending.
  1557. X *    29-jun-87
  1558. X *    - Made adjustmode() use curbp-> instead of curwp->w_bufp-> which
  1559. X *      fixed some bugs in the startup routines.
  1560. X *    - added $lwidth to return the length of the current line
  1561. X *    2-jul-87
  1562. X *    - Added &env <str> which returns the value of the environment
  1563. X *      variable <str> where possible
  1564. X *    - Fixed a NASTY bug in execbuf()..the buffer for the name
  1565. X *      of the buffer to execute was NBUFN long, and got overflowed
  1566. X *      with a long interactive argument.
  1567. X *    3-jul-87
  1568. X *    - Moved the loop to match a key against its binding out of execute()
  1569. X *      to getbind() so it could be used later elsewhere.
  1570. X *    - Added &bind <keyname> which returns the function bound to the
  1571. X *      named key
  1572. X *    - changed execute-file to look in the executable path first...
  1573. X *    6-jul-87
  1574. X *    - changed $curchar to return a newline at the end of a line and
  1575. X *      it no longer advances the cursor
  1576. X *    - a lot of minor changes sent by various people....
  1577. X *    7-jul-87
  1578. X *    - some amiga specific fixes as suggested by Kenn Barry
  1579. X *    - added $line [read/write] that contains the current line in the
  1580. X *      current buffer
  1581. X *    - changed $curcol so setting it beyond the end of the line will
  1582. X *      move the cursor to the end of the line and then fail.
  1583. X *    10-jul-87
  1584. X *    - added a number of fixes and optimizations along with the rest
  1585. X *      of the TURBO-C support as submited by John Maline
  1586. X *    13-jun-87
  1587. X *    - caused dobuf() to copy lastflag to thisflag so the first
  1588. X *      command executed will inherit the lastflag from the command
  1589. X *      before the execute-buffer command. (needed this for smooth
  1590. X *      scrolling to work)
  1591. X *    - made flook() look first in the $HOME directory, then in the
  1592. X *      current directory, then down the $PATH, and then in the
  1593. X *      list in epath.h
  1594. X *    14-jul-87
  1595. X *    - added some fixes for VMS along with support for the SMG
  1596. X *      screen package as submited by Curtis Smith
  1597. X *    15-jul-87
  1598. X *    - fixed M-^H (delete-previous-word) so it can delete the first
  1599. X *      word in a file....I think there may be more of this kind of thing
  1600. X *      to fix.
  1601. X *    16-jul-87
  1602. X *    - added code to allow arbitrary sized lines to be read from files..
  1603. X *      speed up file reading in the process.
  1604. X *    - made out of memory conditions safer.. especial on file reads
  1605. X *    - fixed a bug in bind having to do with uppercasing function
  1606. X *      key names (submitted by Jari Salminen)
  1607. X *    - made ST520 exit in the same resolution that EMACS was started in
  1608. X *      (for the 1040ST)
  1609. X *    [FROZE development and released version 3.9 to USENET]
  1610. X *    {It never made it.....got killed by comp.unix.sources}
  1611. X *    15-sep-87
  1612. X *    - added support for Mark Williams C on the Atari ST
  1613. X *    - made the MALLOC debugging package only conditional on RAMSIZE
  1614. X *    - added code for flagging truncated buffers
  1615. X *    23-sep-87
  1616. X *    - fixed &RIGHT to return the <arg2> rightmost characters
  1617. X *    - fixed a buffer in getval() to be static....things are stabler
  1618. X *      now.
  1619. X *    - moved all the stack size declarations to after include "estruct.h"
  1620. X *      they work a lot better now....... (rather than not at all)
  1621. X *    - made Atari ST spawns all work with MWshell
  1622. X *    - fixed spawning on the 1040ST under MWC
  1623. X *    27-sep-87
  1624. X *    - added &exist function to check to see if a named file exist
  1625. X *    - added &find function to find a file along the PATH
  1626. X *    - added -A switch to run "error.cmd" from command line
  1627. X *    - added $gflags to control startup behavior....
  1628. X *    03-oct-87
  1629. X *    - changed ":c\" to "c:" in epath.h for the AMIGA as suggested
  1630. X *      by Tom Edds
  1631. X *    - added binary and, or, and xor functions as submited by John Maline
  1632. X *      (&band   &bor    and  &bxor)
  1633. X *    - added binary not (&bnot) function
  1634. X *    - added fixes for gotoline() and nextarg() as submited by David
  1635. X *      Dermott
  1636. X *    - fixed return value of $curwidth as submitted by David Dermott
  1637. X *    - fixed several calls to ldelete() to have a long first argument
  1638. X *      (pointed out by David Dermott)
  1639. X *    - Fixed a bug in stock() which prevented uppercase FN bindings as
  1640. X *      pointed out by many people
  1641. X *    - changed dofile() to make sure all executed files don't conflict
  1642. X *      with existing buffer names. Took out cludged code in main.c to
  1643. X *      handle this problem... this solution is better (suggested by
  1644. X *      Don Nash)
  1645. X *    05-oct-87
  1646. X *    - added in John Gamble's code to allow for a replacement regular
  1647. X *      expresion character in MAGIC mode
  1648. X *    [note: under MSDOS  we are still TOO BIG!!!!]
  1649. X *    - added overwrite-string as a new user callable function, and
  1650. X *      lowrite(c) as an internal function for overwriting characters
  1651. X *    - added &xlate function to translate strings according to a
  1652. X *      translation table
  1653. X *    10-oct-87
  1654. X *    - added code to allow emacs to clean its own buffers on exit.
  1655. X *      useful if emacs is used as a subprogram. Conditional on
  1656. X *      the CLEAN definition in estruct.h
  1657. X *    14-oct-87
  1658. X *    - swallowed very hard and switched to LARGE code/LARGE data model
  1659. X *    - packaged and released version 3.9c internally
  1660. X *      (MSDOS executables compiled with TURBO C Large model) 
  1661. X *    16-oct-87
  1662. X *    - temporary fix for FUNCTION keys now includes the Meta-O sequence
  1663. X *      if VT100 is definined (submited by Jeff Lomicka)
  1664. X *    - an VT100 also triggers input.c to force ESC to always
  1665. X *      be interpeted as META as well as the currently bound key
  1666. X *    - fixed a bug in the VMSVT driver as pointed out by Dave Dermott
  1667. X *    - added a size parameter to token() to eliminate problems with
  1668. X *      long variable names. (as sugested by Ray Wallace)
  1669. X *    18-oct-87
  1670. X *    - fixed a bug in the free ram code that did not clear the buffer
  1671. X *      flag causing emacs to ask for more confirnmations on the way out.
  1672. X *    19-oct-87
  1673. X *    - added ^X-$ execute-program call to directly execute a program
  1674. X *      without going through a shell... not all environments have this
  1675. X *      code completed yet (uses shell-command where not)
  1676. X *    [Froze for 3.9d release internally]
  1677. X *    28-oct-87
  1678. X *    - added code for Atari ST DENSE mode and new bell as submited
  1679. X *      by J. C. Benoist
  1680. X *    - made extra CR for ST files conditional on ADDCR. This is only
  1681. X *      needed to make the desktop happy...and is painful for porting
  1682. X *      files (with 2 CR's) elsewhere (Also from J. C. Benoist)
  1683. X *    - added optional more intellegent (and larger) close brace
  1684. X *      insertion code (also from J. C. Benoist)
  1685. X *    4-nov-87
  1686. X *    - fixed AZTEC spawning... all MSDOS spawns should work now
  1687. X *    - a META key while debugging will turn $debug to false
  1688. X *      and continue execution.
  1689. X *    [Froze for version 3.9e USENET release]
  1690. X */
  1691. X
  1692. X#include        <stdio.h>
  1693. X
  1694. X/* make global definitions not external */
  1695. X#define    maindef
  1696. X
  1697. X#include        "estruct.h"    /* global structures and defines */
  1698. X#include    "efunc.h"    /* function declarations and name table    */
  1699. X#include    "edef.h"    /* global definitions */
  1700. X#include    "ebind.h"    /* default key bindings */
  1701. X
  1702. X/* for MSDOS, increase the default stack space */
  1703. X
  1704. X#if    MSDOS & LATTICE
  1705. Xunsigned _stack = 32766;
  1706. X#endif
  1707. X
  1708. X#if    ATARI & MWC
  1709. Xlong _stksize = 32766L;        /* reset stack size (must be even) */
  1710. X#endif
  1711. X
  1712. X#if    MSDOS & AZTEC
  1713. Xint _STKSIZ = 32766/16;        /* stack size in paragraphs */
  1714. Xint _STKRED = 1024;        /* stack checking limit */
  1715. Xint _HEAPSIZ = 4096/16;        /* (in paragraphs) */
  1716. Xint _STKLOW = 0;        /* default is stack above heap (small only) */
  1717. X#endif
  1718. X
  1719. X#if    MSDOS & TURBO
  1720. Xextern unsigned _stklen = 32766;
  1721. X#endif
  1722. X
  1723. X#if     VMS
  1724. X#include        <ssdef.h>
  1725. X#define GOOD    (SS$_NORMAL)
  1726. X#endif
  1727. X
  1728. X#ifndef GOOD
  1729. X#define GOOD    0
  1730. X#endif
  1731. X
  1732. X#if    CALLED
  1733. Xemacs(argc, argv)
  1734. X#else
  1735. Xmain(argc, argv)
  1736. X#endif
  1737. Xint argc;    /* # of arguments */
  1738. Xchar *argv[];    /* argument strings */
  1739. X
  1740. X{
  1741. X        register int    c;        /* command character */
  1742. X        register int    f;        /* default flag */
  1743. X        register int    n;        /* numeric repeat count */
  1744. X        register int    mflag;        /* negative flag on repeat */
  1745. X    register BUFFER *bp;        /* temp buffer pointer */
  1746. X    register int    firstfile;    /* first file flag */
  1747. X    register int    carg;        /* current arg to scan */
  1748. X    register int    startflag;    /* startup executed flag */
  1749. X    BUFFER *firstbp = NULL;        /* ptr to first buffer in cmd line */
  1750. X    int basec;            /* c stripped of meta character */
  1751. X    int viewflag;            /* are we starting in view mode? */
  1752. X        int gotoflag;                   /* do we need to goto a line at start? */
  1753. X        int gline;                      /* if so, what line? */
  1754. X        int searchflag;                 /* Do we need to search at start? */
  1755. X    int saveflag;            /* temp store for lastflag */
  1756. X    int errflag;            /* C error processing? */
  1757. X        char bname[NBUFN];        /* buffer name of file to read */
  1758. X#if    CRYPT
  1759. X    int cryptflag;            /* encrypting on the way in? */
  1760. X    char ekey[NPAT];        /* startup encryption key */
  1761. X#endif
  1762. X    char *strncpy();
  1763. X    extern *pathname[];        /* startup file path/name array */
  1764. X
  1765. X    /* initialize the editor */
  1766. X        vtinit();        /* Display */
  1767. X        edinit("main");        /* Buffers, windows */
  1768. X    varinit();        /* user variables */
  1769. X
  1770. X    viewflag = FALSE;    /* view mode defaults off in command line */
  1771. X    gotoflag = FALSE;    /* set to off to begin with */
  1772. X    searchflag = FALSE;    /* set to off to begin with */
  1773. X    firstfile = TRUE;    /* no file to edit yet */
  1774. X    startflag = FALSE;    /* startup file not executed yet */
  1775. X    errflag = FALSE;    /* not doing C error parsing */
  1776. X#if    CRYPT
  1777. X    cryptflag = FALSE;    /* no encryption by default */
  1778. X#endif
  1779. X#if    CALLED
  1780. X    eexitflag = FALSE;    /* not time to exit yet */
  1781. X#endif
  1782. X
  1783. X    /* Parse the command line */
  1784. X    for (carg = 1; carg < argc; ++carg) {
  1785. X
  1786. X        /* Process Switches */
  1787. X        if (argv[carg][0] == '-') {
  1788. X            switch (argv[carg][1]) {
  1789. X                /* Process Startup macroes */
  1790. X                case 'a':    /* process error file */
  1791. X                case 'A':
  1792. X                    errflag = TRUE;
  1793. X                    break;
  1794. X                case 'e':    /* -e for Edit file */
  1795. X                case 'E':
  1796. X                    viewflag = FALSE;
  1797. X                    break;
  1798. X                case 'g':    /* -g for initial goto */
  1799. X                case 'G':
  1800. X                    gotoflag = TRUE;
  1801. X                    gline = atoi(&argv[carg][2]);
  1802. X                    break;
  1803. X#if    CRYPT
  1804. X                case 'k':    /* -k<key> for code key */
  1805. X                case 'K':
  1806. X                    cryptflag = TRUE;
  1807. X                    strcpy(ekey, &argv[carg][2]);
  1808. X                    break;
  1809. X#endif
  1810. X                case 'r':    /* -r restrictive use */
  1811. X                case 'R':
  1812. X                    restflag = TRUE;
  1813. X                    break;
  1814. X                case 's':    /* -s for initial search string */
  1815. X                case 'S':
  1816. X                    searchflag = TRUE;
  1817. X                    strncpy(pat,&argv[carg][2],NPAT);
  1818. X                    break;
  1819. X                case 'v':    /* -v for View File */
  1820. X                case 'V':
  1821. X                    viewflag = TRUE;
  1822. X                    break;
  1823. X                default:    /* unknown switch */
  1824. X                    /* ignore this for now */
  1825. X                    break;
  1826. X            }
  1827. X
  1828. X        } else if (argv[carg][0]== '@') {
  1829. X
  1830. X            /* Process Startup macroes */
  1831. X            if (startup(&argv[carg][1]) == TRUE)
  1832. X                /* don't execute emacs.rc */
  1833. X                startflag = TRUE;
  1834. X
  1835. X        } else {
  1836. X
  1837. X            /* Process an input file */
  1838. X
  1839. X            /* set up a buffer for this file */
  1840. X                    makename(bname, argv[carg]);
  1841. X            unqname(bname);
  1842. X
  1843. X            /* set this to inactive */
  1844. X            bp = bfind(bname, TRUE, 0);
  1845. X            strcpy(bp->b_fname, argv[carg]);
  1846. X            bp->b_active = FALSE;
  1847. X            if (firstfile) {
  1848. X                firstbp = bp;
  1849. X                firstfile = FALSE;
  1850. X            }
  1851. X
  1852. X            /* set the modes appropriatly */
  1853. X            if (viewflag)
  1854. X                bp->b_mode |= MDVIEW;
  1855. X#if    CRYPT
  1856. X            if (cryptflag) {
  1857. X                bp->b_mode |= MDCRYPT;
  1858. X                crypt((char *)NULL, 0);
  1859. X                crypt(ekey, strlen(ekey));
  1860. X                strncpy(bp->b_key, ekey, NPAT);
  1861. X            }
  1862. X#endif
  1863. X        }
  1864. X    }
  1865. X
  1866. X    /* if we are C error parsing... run it! */
  1867. X    if (errflag) {
  1868. X        if (startup("error.cmd") == TRUE)
  1869. X            startflag = TRUE;
  1870. X    }
  1871. X
  1872. X    /* if invoked with no other startup files,
  1873. X       run the system startup file here */
  1874. X    if (startflag == FALSE) {
  1875. X        startup("");
  1876. X        startflag = TRUE;
  1877. X    }
  1878. X
  1879. X    /* if there are any files to read, read the first one! */
  1880. X    bp = bfind("main", FALSE, 0);
  1881. X    if (firstfile == FALSE && (gflags & GFREAD)) {
  1882. X        swbuffer(firstbp);
  1883. X        curbp->b_mode |= gmode;
  1884. X        zotbuf(bp);
  1885. X    } else
  1886. X        bp->b_mode |= gmode;
  1887. X
  1888. X        /* Deal with startup gotos and searches */
  1889. X        if (gotoflag && searchflag) {
  1890. X            update(FALSE);
  1891. X        mlwrite("[Can not search and goto at the same time!]");
  1892. X    }
  1893. X        else if (gotoflag) {
  1894. X                if (gotoline(TRUE,gline) == FALSE) {
  1895. X                    update(FALSE);
  1896. X            mlwrite("[Bogus goto argument]");
  1897. X        }
  1898. X        } else if (searchflag) {
  1899. X                if (forwhunt(FALSE, 0) == FALSE)
  1900. X                    update(FALSE);
  1901. X        }
  1902. X
  1903. X    /* setup to process commands */
  1904. X        lastflag = 0;                           /* Fake last flags.     */
  1905. X
  1906. Xloop:
  1907. X
  1908. X#if    CALLED
  1909. X    /* if we were called as a subroutine and want to leave, do so */
  1910. X    if (eexitflag)
  1911. X        return(eexitval);
  1912. X#endif 
  1913. X
  1914. X    /* execute the "command" macro...normally null */
  1915. X    saveflag = lastflag;    /* preserve lastflag through this */
  1916. X    execute(META|SPEC|'C', FALSE, 1);
  1917. X    lastflag = saveflag;
  1918. X
  1919. X    /* Fix up the screen    */
  1920. X        update(FALSE);
  1921. X
  1922. X    /* get the next command from the keyboard */
  1923. X    c = getcmd();
  1924. X
  1925. X    /* if there is something on the command line, clear it */
  1926. X        if (mpresf != FALSE) {
  1927. X                mlerase();
  1928. X                update(FALSE);
  1929. X#if    CLRMSG
  1930. X                if (c == ' ')                   /* ITS EMACS does this  */
  1931. X                        goto loop;
  1932. X#endif
  1933. X        }
  1934. X        f = FALSE;
  1935. X        n = 1;
  1936. X
  1937. X    /* do META-# processing if needed */
  1938. X
  1939. X    basec = c & ~META;        /* strip meta char off if there */
  1940. X    if ((c & META) && ((basec >= '0' && basec <= '9') || basec == '-')) {
  1941. X        f = TRUE;        /* there is a # arg */
  1942. X        n = 0;            /* start with a zero default */
  1943. X        mflag = 1;        /* current minus flag */
  1944. X        c = basec;        /* strip the META */
  1945. X        while ((c >= '0' && c <= '9') || (c == '-')) {
  1946. X            if (c == '-') {
  1947. X                /* already hit a minus or digit? */
  1948. X                if ((mflag == -1) || (n != 0))
  1949. X                    break;
  1950. X                mflag = -1;
  1951. X            } else {
  1952. X                n = n * 10 + (c - '0');
  1953. X            }
  1954. X            if ((n == 0) && (mflag == -1))    /* lonely - */
  1955. X                mlwrite("Arg:");
  1956. X            else
  1957. X                mlwrite("Arg: %d",n * mflag);
  1958. X
  1959. X            c = getcmd();    /* get the next key */
  1960. X        }
  1961. X        n = n * mflag;    /* figure in the sign */
  1962. X    }
  1963. X
  1964. X    /* do ^U repeat argument processing */
  1965. X
  1966. X        if (c == reptc) {                  /* ^U, start argument   */
  1967. X                f = TRUE;
  1968. X                n = 4;                          /* with argument of 4 */
  1969. X                mflag = 0;                      /* that can be discarded. */
  1970. X                mlwrite("Arg: 4");
  1971. X                while ((c=getcmd()) >='0' && c<='9' || c==reptc || c=='-'){
  1972. X                        if (c == reptc)
  1973. X                if ((n > 0) == ((n*4) > 0))
  1974. X                                    n = n*4;
  1975. X                            else
  1976. X                                n = 1;
  1977. X                        /*
  1978. X                         * If dash, and start of argument string, set arg.
  1979. X                         * to -1.  Otherwise, insert it.
  1980. X                         */
  1981. X                        else if (c == '-') {
  1982. X                                if (mflag)
  1983. X                                        break;
  1984. X                                n = 0;
  1985. X                                mflag = -1;
  1986. X                        }
  1987. X                        /*
  1988. X                         * If first digit entered, replace previous argument
  1989. X                         * with digit and set sign.  Otherwise, append to arg.
  1990. X                         */
  1991. X                        else {
  1992. X                                if (!mflag) {
  1993. X                                        n = 0;
  1994. X                                        mflag = 1;
  1995. X                                }
  1996. X                                n = 10*n + c - '0';
  1997. X                        }
  1998. X                        mlwrite("Arg: %d", (mflag >=0) ? n : (n ? -n : -1));
  1999. X                }
  2000. X                /*
  2001. X                 * Make arguments preceded by a minus sign negative and change
  2002. X                 * the special argument "^U -" to an effective "^U -1".
  2003. X                 */
  2004. X                if (mflag == -1) {
  2005. X                        if (n == 0)
  2006. X                                n++;
  2007. X                        n = -n;
  2008. X                }
  2009. X        }
  2010. X
  2011. X    /* and execute the command */
  2012. X        execute(c, f, n);
  2013. X        goto loop;
  2014. X}
  2015. X
  2016. X/*
  2017. X * Initialize all of the buffers and windows. The buffer name is passed down
  2018. X * as an argument, because the main routine may have been told to read in a
  2019. X * file by default, and we want the buffer name to be right.
  2020. X */
  2021. Xedinit(bname)
  2022. Xchar    bname[];
  2023. X{
  2024. X        register BUFFER *bp;
  2025. X        register WINDOW *wp;
  2026. X    char *malloc();
  2027. X
  2028. X        bp = bfind(bname, TRUE, 0);             /* First buffer         */
  2029. X        blistp = bfind("[List]", TRUE, BFINVS); /* Buffer list buffer   */
  2030. X        wp = (WINDOW *) malloc(sizeof(WINDOW)); /* First window         */
  2031. X        if (bp==NULL || wp==NULL || blistp==NULL)
  2032. X                exit(1);
  2033. X        curbp  = bp;                            /* Make this current    */
  2034. X        wheadp = wp;
  2035. X        curwp  = wp;
  2036. X        wp->w_wndp  = NULL;                     /* Initialize window    */
  2037. X        wp->w_bufp  = bp;
  2038. X        bp->b_nwnd  = 1;                        /* Displayed.           */
  2039. X        wp->w_linep = bp->b_linep;
  2040. X        wp->w_dotp  = bp->b_linep;
  2041. X        wp->w_doto  = 0;
  2042. X        wp->w_markp = NULL;
  2043. X        wp->w_marko = 0;
  2044. X        wp->w_toprow = 0;
  2045. X#if    COLOR
  2046. X    /* initalize colors to global defaults */
  2047. X    wp->w_fcolor = gfcolor;
  2048. X    wp->w_bcolor = gbcolor;
  2049. X#endif
  2050. X        wp->w_ntrows = term.t_nrow-1;           /* "-1" for mode line.  */
  2051. X        wp->w_force = 0;
  2052. X        wp->w_flag  = WFMODE|WFHARD;            /* Full.                */
  2053. X}
  2054. X
  2055. X/*
  2056. X * This is the general command execution routine. It handles the fake binding
  2057. X * of all the keys to "self-insert". It also clears out the "thisflag" word,
  2058. X * and arranges to move it to the "lastflag", so that the next command can
  2059. X * look at it. Return the status of command.
  2060. X */
  2061. Xexecute(c, f, n)
  2062. X{
  2063. X        register int status;
  2064. X    int (*execfunc)();        /* ptr to function to execute */
  2065. X    int (*getbind())();
  2066. X
  2067. X    /* if the keystroke is a bound function...do it */
  2068. X    execfunc = getbind(c);
  2069. X        if (execfunc != NULL) {
  2070. X        thisflag = 0;
  2071. X        status     = (*execfunc)(f, n);
  2072. X        lastflag = thisflag;
  2073. X        return (status);
  2074. X        }
  2075. X
  2076. X        /*
  2077. X         * If a space was typed, fill column is defined, the argument is non-
  2078. X         * negative, wrap mode is enabled, and we are now past fill column,
  2079. X     * and we are not read-only, perform word wrap.
  2080. X         */
  2081. X        if (c == ' ' && (curwp->w_bufp->b_mode & MDWRAP) && fillcol > 0 &&
  2082. X        n >= 0 && getccol(FALSE) > fillcol &&
  2083. X        (curwp->w_bufp->b_mode & MDVIEW) == FALSE)
  2084. X        execute(META|SPEC|'W', FALSE, 1);
  2085. X
  2086. X        if ((c>=0x20 && c<=0xFF)) {    /* Self inserting.      */
  2087. X                if (n <= 0) {                   /* Fenceposts.          */
  2088. X                        lastflag = 0;
  2089. X                        return (n<0 ? FALSE : TRUE);
  2090. X                }
  2091. X                thisflag = 0;                   /* For the future.      */
  2092. X
  2093. X        /* if we are in overwrite mode, not at eol,
  2094. X           and next char is not a tab or we are at a tab stop,
  2095. X           delete a char forword            */
  2096. X        if (curwp->w_bufp->b_mode & MDOVER &&
  2097. X            curwp->w_doto < curwp->w_dotp->l_used &&
  2098. X            (lgetc(curwp->w_dotp, curwp->w_doto) != '\t' ||
  2099. X             (curwp->w_doto) % 8 == 7))
  2100. X                ldelete(1L, FALSE);
  2101. X
  2102. X        /* do the appropriate insertion */
  2103. X        if (c == '}' && (curbp->b_mode & MDCMOD) != 0)
  2104. X                status = insbrace(n, c);
  2105. X            else if (c == '#' && (curbp->b_mode & MDCMOD) != 0)
  2106. X                status = inspound();
  2107. X            else
  2108. X                    status = linsert(n, c);
  2109. X
  2110. X#if    CFENCE
  2111. X        /* check for CMODE fence matching */
  2112. X        if ((c == '}' || c == ')' || c == ']') &&
  2113. X                (curbp->b_mode & MDCMOD) != 0)
  2114. X            fmatch(c);
  2115. X#endif
  2116. X
  2117. X        /* check auto-save mode */
  2118. X        if (curbp->b_mode & MDASAVE)
  2119. X            if (--gacount == 0) {
  2120. X                /* and save the file if needed */
  2121. X                upscreen(FALSE, 0);
  2122. X                filesave(FALSE, 0);
  2123. X                gacount = gasave;
  2124. X            }
  2125. X
  2126. X                lastflag = thisflag;
  2127. X                return (status);
  2128. X        }
  2129. X    TTbeep();
  2130. X    mlwrite("[Key not bound]");        /* complain        */
  2131. X        lastflag = 0;                           /* Fake last flags.     */
  2132. X        return (FALSE);
  2133. X}
  2134. X
  2135. X/*
  2136. X * Fancy quit command, as implemented by Norm. If the any buffer has
  2137. X * changed do a write on that buffer and exit emacs, otherwise simply exit.
  2138. X */
  2139. Xquickexit(f, n)
  2140. X{
  2141. X    register BUFFER *bp;    /* scanning pointer to buffers */
  2142. X        register BUFFER *oldcb; /* original current buffer */
  2143. X    register int status;
  2144. X
  2145. X        oldcb = curbp;                          /* save in case we fail */
  2146. X
  2147. X    bp = bheadp;
  2148. X    while (bp != NULL) {
  2149. X            if ((bp->b_flag&BFCHG) != 0    /* Changed.             */
  2150. X            && (bp->b_flag&BFINVS) == 0) {    /* Real.                */
  2151. X            curbp = bp;        /* make that buffer cur    */
  2152. X            mlwrite("[Saving %s]",bp->b_fname);
  2153. X            mlwrite("\n");
  2154. X                    if ((status = filesave(f, n)) != TRUE) {
  2155. X                        curbp = oldcb;    /* restore curbp */
  2156. X                        return(status);
  2157. X                    }
  2158. X        }
  2159. X    bp = bp->b_bufp;            /* on to the next buffer */
  2160. X    }
  2161. X        quit(f, n);                             /* conditionally quit   */
  2162. X    return(TRUE);
  2163. X}
  2164. X
  2165. X/*
  2166. X * Quit command. If an argument, always quit. Otherwise confirm if a buffer
  2167. X * has been changed and not written out. Normally bound to "C-X C-C".
  2168. X */
  2169. Xquit(f, n)
  2170. X{
  2171. X        register int    s;
  2172. X
  2173. X        if (f != FALSE                          /* Argument forces it.  */
  2174. X        || anycb() == FALSE                     /* All buffers clean.   */
  2175. X                        /* User says it's OK.   */
  2176. X        || (s=mlyesno("Modified buffers exist. Leave anyway")) == TRUE) {
  2177. X#if    FILOCK
  2178. X        if (lockrel() != TRUE) {
  2179. X            TTputc('\n');
  2180. X            TTputc('\r');
  2181. X            TTclose();
  2182. X            TTkclose();
  2183. X            exit(1);
  2184. X        }
  2185. X#endif
  2186. X                vttidy();
  2187. X        if (f)
  2188. X            exit(n);
  2189. X        else
  2190. X                    exit(GOOD);
  2191. X        }
  2192. X    mlwrite("");
  2193. X        return(s);
  2194. X}
  2195. X
  2196. X/*
  2197. X * Begin a keyboard macro.
  2198. X * Error if not at the top level in keyboard processing. Set up variables and
  2199. X * return.
  2200. X */
  2201. Xctlxlp(f, n)
  2202. X{
  2203. X        if (kbdmode != STOP) {
  2204. X                mlwrite("%%Macro already active");
  2205. X                return(FALSE);
  2206. X        }
  2207. X        mlwrite("[Start macro]");
  2208. X    kbdptr = &kbdm[0];
  2209. X    kbdend = kbdptr;
  2210. X        kbdmode = RECORD;
  2211. X        return (TRUE);
  2212. X}
  2213. X
  2214. X/*
  2215. X * End keyboard macro. Check for the same limit conditions as the above
  2216. X * routine. Set up the variables and return to the caller.
  2217. X */
  2218. Xctlxrp(f, n)
  2219. X{
  2220. X        if (kbdmode == STOP) {
  2221. X                mlwrite("%%Macro not active");
  2222. X                return(FALSE);
  2223. X        }
  2224. X    if (kbdmode == RECORD) {
  2225. X            mlwrite("[End macro]");
  2226. X            kbdmode = STOP;
  2227. X    }
  2228. X        return(TRUE);
  2229. X}
  2230. X
  2231. X/*
  2232. X * Execute a macro.
  2233. X * The command argument is the number of times to loop. Quit as soon as a
  2234. X * command gets an error. Return TRUE if all ok, else FALSE.
  2235. X */
  2236. Xctlxe(f, n)
  2237. X{
  2238. X        if (kbdmode != STOP) {
  2239. X                mlwrite("%%Macro already active");
  2240. X                return(FALSE);
  2241. X        }
  2242. X        if (n <= 0)
  2243. X                return (TRUE);
  2244. X    kbdrep = n;        /* remember how many times to execute */
  2245. X    kbdmode = PLAY;        /* start us in play mode */
  2246. X    kbdptr = &kbdm[0];    /*    at the beginning */
  2247. X    return(TRUE);
  2248. X}
  2249. X
  2250. X/*
  2251. X * Abort.
  2252. X * Beep the beeper. Kill off any keyboard macro, etc., that is in progress.
  2253. X * Sometimes called as a routine, to do general aborting of stuff.
  2254. X */
  2255. Xctrlg(f, n)
  2256. X{
  2257. X        TTbeep();
  2258. X    kbdmode = STOP;
  2259. X    mlwrite("[Aborted]");
  2260. X        return(ABORT);
  2261. X}
  2262. X
  2263. X/* tell the user that this command is illegal while we are in
  2264. X   VIEW (read-only) mode                */
  2265. X
  2266. Xrdonly()
  2267. X
  2268. X{
  2269. X    TTbeep();
  2270. X    mlwrite("[Key illegal in VIEW mode]");
  2271. X    return(FALSE);
  2272. X}
  2273. X
  2274. Xresterr()
  2275. X
  2276. X{
  2277. X    TTbeep();
  2278. X    mlwrite("[That command is RESTRICTED]");
  2279. X    return(FALSE);
  2280. X}
  2281. X
  2282. Xnullproc()    /* user function that does NOTHING */
  2283. X
  2284. X{
  2285. X}
  2286. X
  2287. Xmeta()    /* dummy function for binding to meta prefix */
  2288. X{
  2289. X}
  2290. X
  2291. Xcex()    /* dummy function for binding to control-x prefix */
  2292. X{
  2293. X}
  2294. X
  2295. Xunarg()    /* dummy function for binding to universal-argument */
  2296. X{
  2297. X}
  2298. X
  2299. X/*****        Compiler specific Library functions    ****/
  2300. X
  2301. X#if    MWC86 & MSDOS
  2302. Xmovmem(source, dest, size)
  2303. X
  2304. Xchar *source;    /* mem location to move memory from */
  2305. Xchar *dest;    /* memory location to move text to */
  2306. Xint size;    /* number of bytes to move */
  2307. X
  2308. X{
  2309. X    register int i;
  2310. X
  2311. X    for (i=0; i < size; i++)
  2312. X        *dest++ = *source++;
  2313. X}
  2314. X#endif
  2315. X
  2316. X#if    MSDOS | AMIGA | ST520
  2317. X/*    strncpy:    copy a string...with length restrictions
  2318. X            ALWAYS null terminate
  2319. X*/
  2320. X
  2321. Xchar *strncpy(dst, src, maxlen)
  2322. X
  2323. Xchar *dst;    /* destination of copied string */
  2324. Xchar *src;    /* source */
  2325. Xint maxlen;    /* maximum length */
  2326. X
  2327. X{
  2328. X    char *dptr;    /* ptr into dst */
  2329. X
  2330. X    dptr = dst;
  2331. X    while (*src && (maxlen-- > 0))
  2332. X        *dptr++ = *src++;
  2333. X    *dptr = 0;
  2334. X    return(dst);
  2335. X}
  2336. X#endif
  2337. X
  2338. X#if    RAMSIZE
  2339. X/*    These routines will allow me to track memory usage by placing
  2340. X    a layer on top of the standard system malloc() and free() calls.
  2341. X    with this code defined, the environment variable, $RAM, will
  2342. X    report on the number of bytes allocated via malloc.
  2343. X
  2344. X    with SHOWRAM defined, the number is also posted on the
  2345. X    end of the bottom mode line and is updated whenever it is changed.
  2346. X*/
  2347. X
  2348. X#undef    malloc
  2349. X#undef    free
  2350. X
  2351. Xchar *allocate(nbytes)    /* allocate nbytes and track */
  2352. X
  2353. Xunsigned nbytes;    /* # of bytes to allocate */
  2354. X
  2355. X{
  2356. X    char *mp;    /* ptr returned from malloc */
  2357. X    char *malloc();
  2358. X
  2359. X    mp = malloc(nbytes);
  2360. X    if (mp) {
  2361. X        envram += nbytes;
  2362. X#if    RAMSHOW
  2363. X        dspram();
  2364. X#endif
  2365. X    }
  2366. X
  2367. X    return(mp);
  2368. X}
  2369. X
  2370. Xrelease(mp)    /* release malloced memory and track */
  2371. X
  2372. Xchar *mp;    /* chunk of RAM to release */
  2373. X
  2374. X{
  2375. X    unsigned *lp;    /* ptr to the long containing the block size */
  2376. X
  2377. X    if (mp) {
  2378. X        /* update amount of ram currently malloced */
  2379. X        lp = ((unsigned *)mp) - 1;
  2380. X        envram -= (long)*lp - 2;
  2381. X        free(mp);
  2382. X#if    RAMSHOW
  2383. X        dspram();
  2384. X#endif
  2385. X    }
  2386. X}
  2387. X
  2388. X#if    RAMSHOW
  2389. Xdspram()    /* display the amount of RAM currently malloced */
  2390. X
  2391. X{
  2392. X    char mbuf[20];
  2393. X    char *sp;
  2394. X
  2395. X    TTmove(term.t_nrow - 1, 70);
  2396. X#if    COLOR
  2397. X    TTforg(7);
  2398. X    TTbacg(0);
  2399. X#endif
  2400. X    sprintf(mbuf, "[%lu]", envram);
  2401. X    sp = &mbuf[0];
  2402. X    while (*sp)
  2403. X        TTputc(*sp++);
  2404. X    TTmove(term.t_nrow, 0);
  2405. X    movecursor(term.t_nrow, 0);
  2406. X}
  2407. X#endif
  2408. X#endif
  2409. X
  2410. X/*    On some primitave operation systems, and when emacs is used as
  2411. X    a subprogram to a larger project, emacs needs to de-alloc its
  2412. X    own used memory
  2413. X*/
  2414. X
  2415. X#if    CLEAN
  2416. Xcexit(status)
  2417. X
  2418. Xint status;    /* return status of emacs */
  2419. X
  2420. X{
  2421. X    register BUFFER *bp;    /* buffer list pointer */
  2422. X    register WINDOW *wp;    /* window list pointer */
  2423. X    register WINDOW *tp;    /* temporary window pointer */
  2424. X
  2425. X    /* first clean up the windows */
  2426. X    wp = wheadp;
  2427. X    while (wp) {
  2428. X        tp = wp->w_wndp;
  2429. X        free(wp);
  2430. X        wp = tp;
  2431. X    }
  2432. X    wheadp = NULL;
  2433. X
  2434. X    /* then the buffers */
  2435. X    bp = bheadp;
  2436. X    while (bp) {
  2437. X        bp->b_nwnd = 0;
  2438. X        bp->b_flag = 0;    /* don't say anything about a changed buffer! */
  2439. X        zotbuf(bp);
  2440. X        bp = bheadp;
  2441. X    }
  2442. X
  2443. X    /* and the kill buffer */
  2444. X    kdelete();
  2445. X
  2446. X    /* and the video buffers */
  2447. X    vtfree();
  2448. X
  2449. X    /* and now.. we leave [pick the return if we are a subprogram] */
  2450. X#if    CALLED
  2451. X    eexitflag = TRUE;    /* flag a program exit */
  2452. X    eexitval = status;
  2453. X    return(status);
  2454. X#else
  2455. X#undef    exit
  2456. X    exit(status);
  2457. X#endif
  2458. X}
  2459. X#endif
  2460. FRIDAY_NIGHT
  2461. echo mes.8 completed!
  2462. # That's all folks!
  2463.  
  2464.  
  2465.