home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume4 / uemacs3.6 / part7 < prev    next >
Encoding:
Internet Message Format  |  1986-11-30  |  48.4 KB

  1. Subject: MicroEMACS 3.6 (Part 7 of 8)
  2. Newsgroups: mod.sources
  3. Approved: jpn@panda.UUCP
  4.  
  5. Mod.sources:  Volume 4, Issue 104
  6. Submitted by: ihnp4!itivax!duncan!lawrence
  7.  
  8. echo x - random.c
  9. sed 's/^X//' >random.c <<'*-*-END-of-random.c-*-*'
  10. X/*
  11. X * This file contains the command processing functions for a number of random
  12. X * commands. There is no functional grouping here, for sure.
  13. X */
  14. X
  15. X#include        <stdio.h>
  16. X#include    "estruct.h"
  17. X#include        "edef.h"
  18. X
  19. Xint     tabsize;                        /* Tab size (0: use real tabs)  */
  20. X
  21. X/*
  22. X * Set fill column to n.
  23. X */
  24. Xsetfillcol(f, n)
  25. X{
  26. X        fillcol = n;
  27. X    mlwrite("[Fill column is %d]",n);
  28. X        return(TRUE);
  29. X}
  30. X
  31. X/*
  32. X * Display the current position of the cursor, in origin 1 X-Y coordinates,
  33. X * the character that is under the cursor (in octal), and the fraction of the
  34. X * text that is before the cursor. The displayed column is not the current
  35. X * column, but the column that would be used on an infinite width display.
  36. X * Normally this is bound to "C-X =".
  37. X */
  38. Xshowcpos(f, n)
  39. X{
  40. X        register LINE   *clp;
  41. X        register long   nch;
  42. X        register int    cbo;
  43. X        register long   nbc;
  44. X        register int    cac;
  45. X        register int    ratio;
  46. X        register int    col;
  47. X
  48. X        clp = lforw(curbp->b_linep);            /* Grovel the data.     */
  49. X        cbo = 0;
  50. X        nch = 0;
  51. X        for (;;) {
  52. X                if (clp==curwp->w_dotp && cbo==curwp->w_doto) {
  53. X                        nbc = nch;
  54. X                        if (cbo == llength(clp))
  55. X                                cac = '\n';
  56. X                        else
  57. X                                cac = lgetc(clp, cbo);
  58. X                }
  59. X                if (cbo == llength(clp)) {
  60. X                        if (clp == curbp->b_linep)
  61. X                                break;
  62. X                        clp = lforw(clp);
  63. X                        cbo = 0;
  64. X                } else
  65. X                        ++cbo;
  66. X                ++nch;
  67. X        }
  68. X        col = getccol(FALSE);                   /* Get real column.     */
  69. X        ratio = 0;                              /* Ratio before dot.    */
  70. X        if (nch != 0)
  71. X                ratio = (100L*nbc) / nch;
  72. X        mlwrite("X=%d Y=%d CH=0x%x .=%D (%d%% of %D)",
  73. X                col+1, currow+1, cac, nbc, ratio, nch);
  74. X        return (TRUE);
  75. X}
  76. X
  77. X/*
  78. X * Return current column.  Stop at first non-blank given TRUE argument.
  79. X */
  80. Xgetccol(bflg)
  81. Xint bflg;
  82. X{
  83. X        register int c, i, col;
  84. X        col = 0;
  85. X        for (i=0; i<curwp->w_doto; ++i) {
  86. X                c = lgetc(curwp->w_dotp, i);
  87. X                if (c!=' ' && c!='\t' && bflg)
  88. X                        break;
  89. X                if (c == '\t')
  90. X                        col |= 0x07;
  91. X                else if (c<0x20 || c==0x7F)
  92. X                        ++col;
  93. X                ++col;
  94. X        }
  95. X        return(col);
  96. X}
  97. X
  98. X/*
  99. X * Twiddle the two characters on either side of dot. If dot is at the end of
  100. X * the line twiddle the two characters before it. Return with an error if dot
  101. X * is at the beginning of line; it seems to be a bit pointless to make this
  102. X * work. This fixes up a very common typo with a single stroke. Normally bound
  103. X * to "C-T". This always works within a line, so "WFEDIT" is good enough.
  104. X */
  105. Xtwiddle(f, n)
  106. X{
  107. X        register LINE   *dotp;
  108. X        register int    doto;
  109. X        register int    cl;
  110. X        register int    cr;
  111. X
  112. X    if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  113. X        return(rdonly());    /* we are in read only mode    */
  114. X        dotp = curwp->w_dotp;
  115. X        doto = curwp->w_doto;
  116. X        if (doto==llength(dotp) && --doto<0)
  117. X                return (FALSE);
  118. X        cr = lgetc(dotp, doto);
  119. X        if (--doto < 0)
  120. X                return (FALSE);
  121. X        cl = lgetc(dotp, doto);
  122. X        lputc(dotp, doto+0, cr);
  123. X        lputc(dotp, doto+1, cl);
  124. X        lchange(WFEDIT);
  125. X        return (TRUE);
  126. X}
  127. X
  128. X/*
  129. X * Quote the next character, and insert it into the buffer. All the characters
  130. X * are taken literally, with the exception of the newline, which always has
  131. X * its line splitting meaning. The character is always read, even if it is
  132. X * inserted 0 times, for regularity. Bound to "C-Q"
  133. X */
  134. Xquote(f, n)
  135. X{
  136. X        register int    s;
  137. X        register int    c;
  138. X
  139. X    if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  140. X        return(rdonly());    /* we are in read only mode    */
  141. X        c = (*term.t_getchar)();
  142. X        if (n < 0)
  143. X                return (FALSE);
  144. X        if (n == 0)
  145. X                return (TRUE);
  146. X        if (c == '\n') {
  147. X                do {
  148. X                        s = lnewline();
  149. X                } while (s==TRUE && --n);
  150. X                return (s);
  151. X        }
  152. X        return (linsert(n, c));
  153. X}
  154. X
  155. X/*
  156. X * Set tab size if given non-default argument (n <> 1).  Otherwise, insert a
  157. X * tab into file.  If given argument, n, of zero, change to true tabs.
  158. X * If n > 1, simulate tab stop every n-characters using spaces. This has to be
  159. X * done in this slightly funny way because the tab (in ASCII) has been turned
  160. X * into "C-I" (in 10 bit code) already. Bound to "C-I".
  161. X */
  162. Xtab(f, n)
  163. X{
  164. X        if (n < 0)
  165. X                return (FALSE);
  166. X        if (n == 0 || n > 1) {
  167. X                tabsize = n;
  168. X                return(TRUE);
  169. X        }
  170. X        if (! tabsize)
  171. X                return(linsert(1, '\t'));
  172. X        return(linsert(tabsize - (getccol(FALSE) % tabsize), ' '));
  173. X}
  174. X
  175. X/*
  176. X * Open up some blank space. The basic plan is to insert a bunch of newlines,
  177. X * and then back up over them. Everything is done by the subcommand
  178. X * procerssors. They even handle the looping. Normally this is bound to "C-O".
  179. X */
  180. Xopenline(f, n)
  181. X{
  182. X        register int    i;
  183. X        register int    s;
  184. X
  185. X    if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  186. X        return(rdonly());    /* we are in read only mode    */
  187. X        if (n < 0)
  188. X                return (FALSE);
  189. X        if (n == 0)
  190. X                return (TRUE);
  191. X        i = n;                                  /* Insert newlines.     */
  192. X        do {
  193. X                s = lnewline();
  194. X        } while (s==TRUE && --i);
  195. X        if (s == TRUE)                          /* Then back up overtop */
  196. X                s = backchar(f, n);             /* of them all.         */
  197. X        return (s);
  198. X}
  199. X
  200. X/*
  201. X * Insert a newline. Bound to "C-M". If we are in CMODE, do automatic
  202. X * indentation as specified.
  203. X */
  204. Xnewline(f, n)
  205. X{
  206. X    register int    s;
  207. X
  208. X    if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  209. X        return(rdonly());    /* we are in read only mode    */
  210. X    if (n < 0)
  211. X        return (FALSE);
  212. X
  213. X    /* if we are in C mode and this is a default <NL> */
  214. X    if (n == 1 && (curbp->b_mode & MDCMOD) &&
  215. X        curwp->w_dotp != curbp->b_linep)
  216. X        return(cinsert());
  217. X
  218. X    /* insert some lines */
  219. X    while (n--) {
  220. X        if ((s=lnewline()) != TRUE)
  221. X            return (s);
  222. X    }
  223. X    return (TRUE);
  224. X}
  225. X
  226. Xcinsert()    /* insert a newline and indentation for C */
  227. X
  228. X{
  229. X    register char *cptr;    /* string pointer into text to copy */
  230. X    register int tptr;    /* index to scan into line */
  231. X    register int bracef;    /* was there a brace at the end of line? */
  232. X    register int i;
  233. X    char ichar[NSTRING];    /* buffer to hold indent of last line */
  234. X
  235. X    /* grab a pointer to text to copy indentation from */
  236. X    cptr = &curwp->w_dotp->l_text[0];
  237. X
  238. X    /* check for a brace */
  239. X    tptr = curwp->w_doto - 1;
  240. X    bracef = (cptr[tptr] == '{');
  241. X
  242. X    /* save the indent of the previous line */
  243. X    i = 0;
  244. X    while ((i < tptr) && (cptr[i] == ' ' || cptr[i] == '\t')
  245. X        && (i < NSTRING - 1)) {
  246. X        ichar[i] = cptr[i];
  247. X        ++i;
  248. X    }
  249. X    ichar[i] = 0;        /* terminate it */
  250. X
  251. X    /* put in the newline */
  252. X    if (lnewline() == FALSE)
  253. X        return(FALSE);
  254. X
  255. X    /* and the saved indentation */
  256. X    i = 0;
  257. X    while (ichar[i])
  258. X        linsert(1, ichar[i++]);
  259. X
  260. X    /* and one more tab for a brace */
  261. X    if (bracef)
  262. X        tab(FALSE, 1);
  263. X
  264. X    return(TRUE);
  265. X}
  266. X
  267. Xinsbrace(n, c)    /* insert a brace into the text here...we are in CMODE */
  268. X
  269. Xint n;    /* repeat count */
  270. Xint c;    /* brace to insert (always { for now) */
  271. X
  272. X{
  273. X    register int ch;    /* last character before input */
  274. X    register int i;
  275. X    register int target;    /* column brace should go after */
  276. X
  277. X    /* if we are at the begining of the line, no go */
  278. X    if (curwp->w_doto == 0)
  279. X        return(linsert(n,c));
  280. X        
  281. X    /* scan to see if all space before this is white space */
  282. X    for (i = curwp->w_doto - 1; i >= 0; --i) {
  283. X        ch = lgetc(curwp->w_dotp, i);
  284. X        if (ch != ' ' && ch != '\t')
  285. X            return(linsert(n, c));
  286. X    }
  287. X
  288. X    /* delete back first */
  289. X    target = getccol(FALSE);    /* calc where we will delete to */
  290. X    target -= 1;
  291. X    target -= target % (tabsize == 0 ? 8 : tabsize);
  292. X    while (getccol(FALSE) > target)
  293. X        backdel(FALSE, 1);
  294. X
  295. X    /* and insert the required brace(s) */
  296. X    return(linsert(n, c));
  297. X}
  298. X
  299. Xinspound()    /* insert a # into the text here...we are in CMODE */
  300. X
  301. X{
  302. X    register int ch;    /* last character before input */
  303. X    register int i;
  304. X
  305. X    /* if we are at the begining of the line, no go */
  306. X    if (curwp->w_doto == 0)
  307. X        return(linsert(1,'#'));
  308. X        
  309. X    /* scan to see if all space before this is white space */
  310. X    for (i = curwp->w_doto - 1; i >= 0; --i) {
  311. X        ch = lgetc(curwp->w_dotp, i);
  312. X        if (ch != ' ' && ch != '\t')
  313. X            return(linsert(1, '#'));
  314. X    }
  315. X
  316. X    /* delete back first */
  317. X    while (getccol(FALSE) > 1)
  318. X        backdel(FALSE, 1);
  319. X
  320. X    /* and insert the required pound */
  321. X    return(linsert(1, '#'));
  322. X}
  323. X
  324. X/*
  325. X * Delete blank lines around dot. What this command does depends if dot is
  326. X * sitting on a blank line. If dot is sitting on a blank line, this command
  327. X * deletes all the blank lines above and below the current line. If it is
  328. X * sitting on a non blank line then it deletes all of the blank lines after
  329. X * the line. Normally this command is bound to "C-X C-O". Any argument is
  330. X * ignored.
  331. X */
  332. Xdeblank(f, n)
  333. X{
  334. X        register LINE   *lp1;
  335. X        register LINE   *lp2;
  336. X        register int    nld;
  337. X
  338. X    if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  339. X        return(rdonly());    /* we are in read only mode    */
  340. X        lp1 = curwp->w_dotp;
  341. X        while (llength(lp1)==0 && (lp2=lback(lp1))!=curbp->b_linep)
  342. X                lp1 = lp2;
  343. X        lp2 = lp1;
  344. X        nld = 0;
  345. X        while ((lp2=lforw(lp2))!=curbp->b_linep && llength(lp2)==0)
  346. X                ++nld;
  347. X        if (nld == 0)
  348. X                return (TRUE);
  349. X        curwp->w_dotp = lforw(lp1);
  350. X        curwp->w_doto = 0;
  351. X        return (ldelete(nld));
  352. X}
  353. X
  354. X/*
  355. X * Insert a newline, then enough tabs and spaces to duplicate the indentation
  356. X * of the previous line. Assumes tabs are every eight characters. Quite simple.
  357. X * Figure out the indentation of the current line. Insert a newline by calling
  358. X * the standard routine. Insert the indentation by inserting the right number
  359. X * of tabs and spaces. Return TRUE if all ok. Return FALSE if one of the
  360. X * subcomands failed. Normally bound to "C-J".
  361. X */
  362. Xindent(f, n)
  363. X{
  364. X        register int    nicol;
  365. X        register int    c;
  366. X        register int    i;
  367. X
  368. X    if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  369. X        return(rdonly());    /* we are in read only mode    */
  370. X        if (n < 0)
  371. X                return (FALSE);
  372. X        while (n--) {
  373. X                nicol = 0;
  374. X                for (i=0; i<llength(curwp->w_dotp); ++i) {
  375. X                        c = lgetc(curwp->w_dotp, i);
  376. X                        if (c!=' ' && c!='\t')
  377. X                                break;
  378. X                        if (c == '\t')
  379. X                                nicol |= 0x07;
  380. X                        ++nicol;
  381. X                }
  382. X                if (lnewline() == FALSE
  383. X                || ((i=nicol/8)!=0 && linsert(i, '\t')==FALSE)
  384. X                || ((i=nicol%8)!=0 && linsert(i,  ' ')==FALSE))
  385. X                        return (FALSE);
  386. X        }
  387. X        return (TRUE);
  388. X}
  389. X
  390. X/*
  391. X * Delete forward. This is real easy, because the basic delete routine does
  392. X * all of the work. Watches for negative arguments, and does the right thing.
  393. X * If any argument is present, it kills rather than deletes, to prevent loss
  394. X * of text if typed with a big argument. Normally bound to "C-D".
  395. X */
  396. Xforwdel(f, n)
  397. X{
  398. X    if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  399. X        return(rdonly());    /* we are in read only mode    */
  400. X        if (n < 0)
  401. X                return (backdel(f, -n));
  402. X        if (f != FALSE) {                       /* Really a kill.       */
  403. X                if ((lastflag&CFKILL) == 0)
  404. X                        kdelete();
  405. X                thisflag |= CFKILL;
  406. X        }
  407. X        return (ldelete(n, f));
  408. X}
  409. X
  410. X/*
  411. X * Delete backwards. This is quite easy too, because it's all done with other
  412. X * functions. Just move the cursor back, and delete forwards. Like delete
  413. X * forward, this actually does a kill if presented with an argument. Bound to
  414. X * both "RUBOUT" and "C-H".
  415. X */
  416. Xbackdel(f, n)
  417. X{
  418. X        register int    s;
  419. X
  420. X    if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  421. X        return(rdonly());    /* we are in read only mode    */
  422. X        if (n < 0)
  423. X                return (forwdel(f, -n));
  424. X        if (f != FALSE) {                       /* Really a kill.       */
  425. X                if ((lastflag&CFKILL) == 0)
  426. X                        kdelete();
  427. X                thisflag |= CFKILL;
  428. X        }
  429. X        if ((s=backchar(f, n)) == TRUE)
  430. X                s = ldelete(n, f);
  431. X        return (s);
  432. X}
  433. X
  434. X/*
  435. X * Kill text. If called without an argument, it kills from dot to the end of
  436. X * the line, unless it is at the end of the line, when it kills the newline.
  437. X * If called with an argument of 0, it kills from the start of the line to dot.
  438. X * If called with a positive argument, it kills from dot forward over that
  439. X * number of newlines. If called with a negative argument it kills backwards
  440. X * that number of newlines. Normally bound to "C-K".
  441. X */
  442. Xkilltext(f, n)
  443. X{
  444. X        register int    chunk;
  445. X        register LINE   *nextp;
  446. X
  447. X    if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  448. X        return(rdonly());    /* we are in read only mode    */
  449. X        if ((lastflag&CFKILL) == 0)             /* Clear kill buffer if */
  450. X                kdelete();                      /* last wasn't a kill.  */
  451. X        thisflag |= CFKILL;
  452. X        if (f == FALSE) {
  453. X                chunk = llength(curwp->w_dotp)-curwp->w_doto;
  454. X                if (chunk == 0)
  455. X                        chunk = 1;
  456. X        } else if (n == 0) {
  457. X                chunk = curwp->w_doto;
  458. X                curwp->w_doto = 0;
  459. X        } else if (n > 0) {
  460. X                chunk = llength(curwp->w_dotp)-curwp->w_doto+1;
  461. X                nextp = lforw(curwp->w_dotp);
  462. X                while (--n) {
  463. X                        if (nextp == curbp->b_linep)
  464. X                                return (FALSE);
  465. X                        chunk += llength(nextp)+1;
  466. X                        nextp = lforw(nextp);
  467. X                }
  468. X        } else {
  469. X                mlwrite("neg kill");
  470. X                return (FALSE);
  471. X        }
  472. X        return (ldelete(chunk, TRUE));
  473. X}
  474. X
  475. X/*
  476. X * Yank text back from the kill buffer. This is really easy. All of the work
  477. X * is done by the standard insert routines. All you do is run the loop, and
  478. X * check for errors. Bound to "C-Y".
  479. X */
  480. Xyank(f, n)
  481. X{
  482. X        register int    c;
  483. X        register int    i;
  484. X        extern   int    kused;
  485. X
  486. X    if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  487. X        return(rdonly());    /* we are in read only mode    */
  488. X        if (n < 0)
  489. X                return (FALSE);
  490. X        while (n--) {
  491. X                i = 0;
  492. X                while ((c=kremove(i)) >= 0) {
  493. X                        if (c == '\n') {
  494. X                                if (lnewline(FALSE, 1) == FALSE)
  495. X                                        return (FALSE);
  496. X                        } else {
  497. X                                if (linsert(1, c) == FALSE)
  498. X                                        return (FALSE);
  499. X                        }
  500. X                        ++i;
  501. X                }
  502. X        }
  503. X        return (TRUE);
  504. X}
  505. X
  506. Xsetmode(f, n)    /* prompt and set an editor mode */
  507. X
  508. Xint f, n;    /* default and argument */
  509. X
  510. X{
  511. X    adjustmode(TRUE, FALSE);
  512. X}
  513. X
  514. Xdelmode(f, n)    /* prompt and delete an editor mode */
  515. X
  516. Xint f, n;    /* default and argument */
  517. X
  518. X{
  519. X    adjustmode(FALSE, FALSE);
  520. X}
  521. X
  522. Xsetgmode(f, n)    /* prompt and set a global editor mode */
  523. X
  524. Xint f, n;    /* default and argument */
  525. X
  526. X{
  527. X    adjustmode(TRUE, TRUE);
  528. X}
  529. X
  530. Xdelgmode(f, n)    /* prompt and delete a global editor mode */
  531. X
  532. Xint f, n;    /* default and argument */
  533. X
  534. X{
  535. X    adjustmode(FALSE, TRUE);
  536. X}
  537. X
  538. Xadjustmode(kind, global)    /* change the editor mode status */
  539. X
  540. Xint kind;    /* true = set,        false = delete */
  541. Xint global;    /* true = global flag,    false = current buffer flag */
  542. X{
  543. X    register char prompt[50];    /* string to prompt user with */
  544. X    register char *scan;        /* scanning pointer to convert prompt */
  545. X    register int i;            /* loop index */
  546. X    char cbuf[NPAT];        /* buffer to recieve mode name into */
  547. X
  548. X    /* build the proper prompt string */
  549. X    if (global)
  550. X        strcpy(prompt,"Global mode to ");
  551. X    else
  552. X        strcpy(prompt,"Mode to ");
  553. X
  554. X    if (kind == TRUE)
  555. X        strcat(prompt, "add: ");
  556. X    else
  557. X        strcat(prompt, "delete: ");
  558. X
  559. X    /* prompt the user and get an answer */
  560. X
  561. X    mlreply(prompt, cbuf, NPAT - 1);
  562. X
  563. X    /* make it uppercase */
  564. X
  565. X    scan = cbuf;
  566. X    while (*scan != 0) {
  567. X        if (*scan >= 'a' && *scan <= 'z')
  568. X            *scan = *scan - 32;
  569. X        scan++;
  570. X    }
  571. X
  572. X    /* test it against the modes we know */
  573. X
  574. X    for (i=0; i < NUMMODES; i++) {
  575. X        if (strcmp(cbuf, modename[i]) == 0) {
  576. X            /* finding a match, we process it */
  577. X            if (kind == TRUE)
  578. X                if (global)
  579. X                    gmode |= (1 << i);
  580. X                else
  581. X                    curwp->w_bufp->b_mode |= (1 << i);
  582. X            else
  583. X                if (global)
  584. X                    gmode &= ~(1 << i);
  585. X                else
  586. X                    curwp->w_bufp->b_mode &= ~(1 << i);
  587. X            /* display new mode line */
  588. X            if (global == 0)
  589. X                upmode();
  590. X            mlerase();    /* erase the junk */
  591. X            return(TRUE);
  592. X        }
  593. X    }
  594. X
  595. X    mlwrite("No such mode!");
  596. X    return(FALSE);
  597. X}
  598. *-*-END-of-random.c-*-*
  599. echo x - region.c
  600. sed 's/^X//' >region.c <<'*-*-END-of-region.c-*-*'
  601. X/*
  602. X * The routines in this file
  603. X * deal with the region, that magic space
  604. X * between "." and mark. Some functions are
  605. X * commands. Some functions are just for
  606. X * internal use.
  607. X */
  608. X#include        <stdio.h>
  609. X#include    "estruct.h"
  610. X#include        "edef.h"
  611. X
  612. X/*
  613. X * Kill the region. Ask "getregion"
  614. X * to figure out the bounds of the region.
  615. X * Move "." to the start, and kill the characters.
  616. X * Bound to "C-W".
  617. X */
  618. Xkillregion(f, n)
  619. X{
  620. X        register int    s;
  621. X        REGION          region;
  622. X
  623. X    if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  624. X        return(rdonly());    /* we are in read only mode    */
  625. X        if ((s=getregion(®ion)) != TRUE)
  626. X                return (s);
  627. X        if ((lastflag&CFKILL) == 0)             /* This is a kill type  */
  628. X                kdelete();                      /* command, so do magic */
  629. X        thisflag |= CFKILL;                     /* kill buffer stuff.   */
  630. X        curwp->w_dotp = region.r_linep;
  631. X        curwp->w_doto = region.r_offset;
  632. X        return (ldelete(region.r_size, TRUE));
  633. X}
  634. X
  635. X/*
  636. X * Copy all of the characters in the
  637. X * region to the kill buffer. Don't move dot
  638. X * at all. This is a bit like a kill region followed
  639. X * by a yank. Bound to "M-W".
  640. X */
  641. Xcopyregion(f, n)
  642. X{
  643. X        register LINE   *linep;
  644. X        register int    loffs;
  645. X        register int    s;
  646. X        REGION          region;
  647. X
  648. X        if ((s=getregion(®ion)) != TRUE)
  649. X                return (s);
  650. X        if ((lastflag&CFKILL) == 0)             /* Kill type command.   */
  651. X                kdelete();
  652. X        thisflag |= CFKILL;
  653. X        linep = region.r_linep;                 /* Current line.        */
  654. X        loffs = region.r_offset;                /* Current offset.      */
  655. X        while (region.r_size--) {
  656. X                if (loffs == llength(linep)) {  /* End of line.         */
  657. X                        if ((s=kinsert('\n')) != TRUE)
  658. X                                return (s);
  659. X                        linep = lforw(linep);
  660. X                        loffs = 0;
  661. X                } else {                        /* Middle of line.      */
  662. X                        if ((s=kinsert(lgetc(linep, loffs))) != TRUE)
  663. X                                return (s);
  664. X                        ++loffs;
  665. X                }
  666. X        }
  667. X        return (TRUE);
  668. X}
  669. X
  670. X/*
  671. X * Lower case region. Zap all of the upper
  672. X * case characters in the region to lower case. Use
  673. X * the region code to set the limits. Scan the buffer,
  674. X * doing the changes. Call "lchange" to ensure that
  675. X * redisplay is done in all buffers. Bound to
  676. X * "C-X C-L".
  677. X */
  678. Xlowerregion(f, n)
  679. X{
  680. X        register LINE   *linep;
  681. X        register int    loffs;
  682. X        register int    c;
  683. X        register int    s;
  684. X        REGION          region;
  685. X
  686. X    if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  687. X        return(rdonly());    /* we are in read only mode    */
  688. X        if ((s=getregion(®ion)) != TRUE)
  689. X                return (s);
  690. X        lchange(WFHARD);
  691. X        linep = region.r_linep;
  692. X        loffs = region.r_offset;
  693. X        while (region.r_size--) {
  694. X                if (loffs == llength(linep)) {
  695. X                        linep = lforw(linep);
  696. X                        loffs = 0;
  697. X                } else {
  698. X                        c = lgetc(linep, loffs);
  699. X                        if (c>='A' && c<='Z')
  700. X                                lputc(linep, loffs, c+'a'-'A');
  701. X                        ++loffs;
  702. X                }
  703. X        }
  704. X        return (TRUE);
  705. X}
  706. X
  707. X/*
  708. X * Upper case region. Zap all of the lower
  709. X * case characters in the region to upper case. Use
  710. X * the region code to set the limits. Scan the buffer,
  711. X * doing the changes. Call "lchange" to ensure that
  712. X * redisplay is done in all buffers. Bound to
  713. X * "C-X C-L".
  714. X */
  715. Xupperregion(f, n)
  716. X{
  717. X        register LINE   *linep;
  718. X        register int    loffs;
  719. X        register int    c;
  720. X        register int    s;
  721. X        REGION          region;
  722. X
  723. X    if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  724. X        return(rdonly());    /* we are in read only mode    */
  725. X        if ((s=getregion(®ion)) != TRUE)
  726. X                return (s);
  727. X        lchange(WFHARD);
  728. X        linep = region.r_linep;
  729. X        loffs = region.r_offset;
  730. X        while (region.r_size--) {
  731. X                if (loffs == llength(linep)) {
  732. X                        linep = lforw(linep);
  733. X                        loffs = 0;
  734. X                } else {
  735. X                        c = lgetc(linep, loffs);
  736. X                        if (c>='a' && c<='z')
  737. X                                lputc(linep, loffs, c-'a'+'A');
  738. X                        ++loffs;
  739. X                }
  740. X        }
  741. X        return (TRUE);
  742. X}
  743. X
  744. X/*
  745. X * This routine figures out the
  746. X * bounds of the region in the current window, and
  747. X * fills in the fields of the "REGION" structure pointed
  748. X * to by "rp". Because the dot and mark are usually very
  749. X * close together, we scan outward from dot looking for
  750. X * mark. This should save time. Return a standard code.
  751. X * Callers of this routine should be prepared to get
  752. X * an "ABORT" status; we might make this have the
  753. X * conform thing later.
  754. X */
  755. Xgetregion(rp)
  756. Xregister REGION *rp;
  757. X{
  758. X        register LINE   *flp;
  759. X        register LINE   *blp;
  760. X        int    fsize;
  761. X        register int    bsize;
  762. X
  763. X        if (curwp->w_markp == NULL) {
  764. X                mlwrite("No mark set in this window");
  765. X                return (FALSE);
  766. X        }
  767. X        if (curwp->w_dotp == curwp->w_markp) {
  768. X                rp->r_linep = curwp->w_dotp;
  769. X                if (curwp->w_doto < curwp->w_marko) {
  770. X                        rp->r_offset = curwp->w_doto;
  771. X                        rp->r_size = curwp->w_marko-curwp->w_doto;
  772. X                } else {
  773. X                        rp->r_offset = curwp->w_marko;
  774. X                        rp->r_size = curwp->w_doto-curwp->w_marko;
  775. X                }
  776. X                return (TRUE);
  777. X        }
  778. X        blp = curwp->w_dotp;
  779. X        bsize = curwp->w_doto;
  780. X        flp = curwp->w_dotp;
  781. X        fsize = llength(flp)-curwp->w_doto+1;
  782. X        while (flp!=curbp->b_linep || lback(blp)!=curbp->b_linep) {
  783. X                if (flp != curbp->b_linep) {
  784. X                        flp = lforw(flp);
  785. X                        if (flp == curwp->w_markp) {
  786. X                                rp->r_linep = curwp->w_dotp;
  787. X                                rp->r_offset = curwp->w_doto;
  788. X                                rp->r_size = fsize+curwp->w_marko;
  789. X                                return (TRUE);
  790. X                        }
  791. X                        fsize += llength(flp)+1;
  792. X                }
  793. X                if (lback(blp) != curbp->b_linep) {
  794. X                        blp = lback(blp);
  795. X                        bsize += llength(blp)+1;
  796. X                        if (blp == curwp->w_markp) {
  797. X                                rp->r_linep = blp;
  798. X                                rp->r_offset = curwp->w_marko;
  799. X                                rp->r_size = bsize - curwp->w_marko;
  800. X                                return (TRUE);
  801. X                        }
  802. X                }
  803. X        }
  804. X        mlwrite("Bug: lost mark");
  805. X        return (FALSE);
  806. X}
  807. *-*-END-of-region.c-*-*
  808. echo x - search.c
  809. sed 's/^X//' >search.c <<'*-*-END-of-search.c-*-*'
  810. X/*
  811. X * The functions in this file implement commands that search in the forward
  812. X * and backward directions. There are no special characters in the search
  813. X * strings. Probably should have a regular expression search, or something
  814. X * like that.
  815. X *
  816. X */
  817. X
  818. X#include        <stdio.h>
  819. X#include    "estruct.h"
  820. X#include        "edef.h"
  821. X
  822. X/*
  823. X * Search forward. Get a search string from the user, and search, beginning at
  824. X * ".", for the string. If found, reset the "." to be just after the match
  825. X * string, and [perhaps] repaint the display. Bound to "C-S".
  826. X */
  827. X
  828. X/*    string search input parameters    */
  829. X
  830. X#define    PTBEG    1    /* leave the point at the begining on search */
  831. X#define    PTEND    2    /* leave the point at the end on search */
  832. X
  833. Xforwsearch(f, n)
  834. X
  835. X{
  836. X    register int status;
  837. X
  838. X    /* resolve the repeat count */
  839. X    if (n == 0)
  840. X        n = 1;
  841. X    if (n < 1)    /* search backwards */
  842. X        return(backsearch(f, -n));
  843. X
  844. X    /* ask the user for the text of a pattern */
  845. X    if ((status = readpattern("Search")) != TRUE)
  846. X        return(status);
  847. X
  848. X    /* search for the pattern */
  849. X    while (n-- > 0) {
  850. X        if ((status = forscan(&pat[0],PTEND)) == FALSE)
  851. X            break;
  852. X    }
  853. X
  854. X    /* and complain if not there */
  855. X    if (status == FALSE)
  856. X        mlwrite("Not found");
  857. X    return(status);
  858. X}
  859. X
  860. Xforwhunt(f, n)
  861. X
  862. X{
  863. X    register int status;
  864. X
  865. X    /* resolve the repeat count */
  866. X    if (n == 0)
  867. X        n = 1;
  868. X    if (n < 1)    /* search backwards */
  869. X        return(backhunt(f, -n));
  870. X
  871. X    /* Make sure a pattern exists */
  872. X    if (pat[0] == 0) {
  873. X        mlwrite("No pattern set");
  874. X        return(FALSE);
  875. X    }
  876. X
  877. X    /* search for the pattern */
  878. X    while (n-- > 0) {
  879. X        if ((status = forscan(&pat[0],PTEND)) == FALSE)
  880. X            break;
  881. X    }
  882. X
  883. X    /* and complain if not there */
  884. X    if (status == FALSE)
  885. X        mlwrite("Not found");
  886. X    return(status);
  887. X}
  888. X
  889. X/*
  890. X * Reverse search. Get a search string from the user, and search, starting at
  891. X * "." and proceeding toward the front of the buffer. If found "." is left
  892. X * pointing at the first character of the pattern [the last character that was
  893. X * matched]. Bound to "C-R".
  894. X */
  895. Xbacksearch(f, n)
  896. X
  897. X{
  898. X    register int s;
  899. X
  900. X    /* resolve null and negative arguments */
  901. X    if (n == 0)
  902. X        n = 1;
  903. X    if (n < 1)
  904. X        return(forwsearch(f, -n));
  905. X
  906. X    /* get a pattern to search */
  907. X    if ((s = readpattern("Reverse search")) != TRUE)
  908. X        return(s);
  909. X
  910. X    /* and go search for it */
  911. X    bsearch(f,n);
  912. X}
  913. X
  914. Xbackhunt(f, n)    /* hunt backward for the last search string entered */
  915. X
  916. X{
  917. X    /* resolve null and negative arguments */
  918. X    if (n == 0)
  919. X        n = 1;
  920. X    if (n < 1)
  921. X        return(forwhunt(f, -n));
  922. X
  923. X    /* Make sure a pattern exists */
  924. X    if (pat[0] == 0) {
  925. X        mlwrite("No pattern set");
  926. X        return(FALSE);
  927. X    }
  928. X
  929. X    /* and go search for it */
  930. X    bsearch(f,n);
  931. X}
  932. X
  933. Xbsearch(f, n)
  934. X
  935. X{
  936. X    register LINE *clp;
  937. X    register int cbo;
  938. X    register LINE *tlp;
  939. X    register int tbo;
  940. X    register int c;
  941. X    register char *epp;
  942. X    register char *pp;
  943. X
  944. X    /* find a pointer to the end of the pattern */
  945. X    for (epp = &pat[0]; epp[1] != 0; ++epp)
  946. X        ;
  947. X
  948. X    /* make local copies of the starting location */
  949. X    clp = curwp->w_dotp;
  950. X    cbo = curwp->w_doto;
  951. X
  952. X    while (n-- > 0) {
  953. X        for (;;) {
  954. X            /* if we are at the begining of the line, wrap back around */
  955. X            if (cbo == 0) {
  956. X                clp = lback(clp);
  957. X
  958. X                if (clp == curbp->b_linep) {
  959. X                    mlwrite("Not found");
  960. X                    return(FALSE);
  961. X                }
  962. X
  963. X                cbo = llength(clp)+1;
  964. X            }
  965. X
  966. X            /* fake the <NL> at the end of a line */
  967. X            if (--cbo == llength(clp))
  968. X                c = '\n';
  969. X            else
  970. X                c = lgetc(clp, cbo);
  971. X
  972. X            /* check for a match against the end of the pattern */
  973. X            if (eq(c, *epp) != FALSE) {
  974. X                tlp = clp;
  975. X                tbo = cbo;
  976. X                pp  = epp;
  977. X
  978. X                /* scanning backwards through the rest of the
  979. X                   pattern looking for a match            */
  980. X                while (pp != &pat[0]) {
  981. X                    /* wrap across a line break */
  982. X                    if (tbo == 0) {
  983. X                        tlp = lback(tlp);
  984. X                        if (tlp == curbp->b_linep)
  985. X                            goto fail;
  986. X
  987. X                        tbo = llength(tlp)+1;
  988. X                    }
  989. X
  990. X                    /* fake the <NL> */
  991. X                    if (--tbo == llength(tlp))
  992. X                        c = '\n';
  993. X                    else
  994. X                        c = lgetc(tlp, tbo);
  995. X
  996. X                    if (eq(c, *--pp) == FALSE)
  997. X                        goto fail;
  998. X                }
  999. X
  1000. X                /* A Match!  reset the current cursor */
  1001. X                curwp->w_dotp  = tlp;
  1002. X                curwp->w_doto  = tbo;
  1003. X                curwp->w_flag |= WFMOVE;
  1004. X                goto next;
  1005. X            }
  1006. Xfail:;
  1007. X        }
  1008. Xnext:;
  1009. X    }
  1010. X    return(TRUE);
  1011. X}
  1012. X
  1013. X/*
  1014. X * Compare two characters. The "bc" comes from the buffer. It has it's case
  1015. X * folded out. The "pc" is from the pattern.
  1016. X */
  1017. Xeq(bc, pc)
  1018. X    int bc;
  1019. X    int pc;
  1020. X
  1021. X{
  1022. X    if ((curwp->w_bufp->b_mode & MDEXACT) == 0) {
  1023. X        if (bc>='a' && bc<='z')
  1024. X            bc -= 0x20;
  1025. X
  1026. X        if (pc>='a' && pc<='z')
  1027. X            pc -= 0x20;
  1028. X    }
  1029. X
  1030. X    if (bc == pc)
  1031. X        return(TRUE);
  1032. X
  1033. X    return(FALSE);
  1034. X}
  1035. X
  1036. X/*
  1037. X * Read a pattern. Stash it in the external variable "pat". The "pat" is not
  1038. X * updated if the user types in an empty line. If the user typed an empty line,
  1039. X * and there is no old pattern, it is an error. Display the old pattern, in the
  1040. X * style of Jeff Lomicka. There is some do-it-yourself control expansion.
  1041. X * change to using <ESC> to delemit the end-of-pattern to allow <NL>s in
  1042. X * the search string.
  1043. X */
  1044. Xreadpattern(prompt)
  1045. X
  1046. Xchar *prompt;
  1047. X
  1048. X{
  1049. X    register int s;
  1050. X    char tpat[NPAT+20];
  1051. X
  1052. X    strcpy(tpat, prompt);    /* copy prompt to output string */
  1053. X    strcat(tpat, " [");    /* build new prompt string */
  1054. X    expandp(&pat[0], &tpat[strlen(tpat)], NPAT/2);    /* add old pattern */
  1055. X    strcat(tpat, "]<ESC>: ");
  1056. X
  1057. X    s = mlreplyt(tpat, tpat, NPAT, 27);    /* Read pattern */
  1058. X
  1059. X    if (s == TRUE)                /* Specified */
  1060. X        strcpy(pat, tpat);
  1061. X    else if (s == FALSE && pat[0] != 0)    /* CR, but old one */
  1062. X        s = TRUE;
  1063. X
  1064. X    return(s);
  1065. X}
  1066. X
  1067. Xsreplace(f, n)    /*    Search and replace (ESC-R)    */
  1068. X
  1069. Xint f;        /* default flag */
  1070. Xint n;        /* # of repetitions wanted */
  1071. X
  1072. X{
  1073. X    return(replaces(FALSE, f, n));
  1074. X}
  1075. X
  1076. Xqreplace(f, n)    /*    search and replace with query (ESC-CTRL-R)    */
  1077. X
  1078. Xint f;        /* default flag */
  1079. Xint n;        /* # of repetitions wanted */
  1080. X
  1081. X{
  1082. X    return(replaces(TRUE, f, n));
  1083. X}
  1084. X
  1085. X/*    replaces:    search for a string and replace it with another
  1086. X            string. query might be enabled (according to
  1087. X            kind).                        */
  1088. Xreplaces(kind, f, n)
  1089. X
  1090. Xint kind;    /* Query enabled flag */
  1091. Xint f;        /* default flag */
  1092. Xint n;        /* # of repetitions wanted */
  1093. X
  1094. X{
  1095. X    register int i;        /* loop index */
  1096. X    register int s;        /* success flag on pattern inputs */
  1097. X    register int slength,
  1098. X             rlength;    /* length of search and replace strings */
  1099. X    register int numsub;    /* number of substitutions */
  1100. X    register int nummatch;    /* number of found matches */
  1101. X    int nlflag;        /* last char of search string a <NL>? */
  1102. X    int nlrepl;        /* was a replace done on the last line? */
  1103. X    char tmpc;        /* temporary character */
  1104. X    char c;            /* input char for query */
  1105. X    char tpat[NPAT];    /* temporary to hold search pattern */
  1106. X    LINE *origline;        /* original "." position */
  1107. X    int origoff;        /* and offset (for . query option) */
  1108. X
  1109. X    if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  1110. X        return(rdonly());    /* we are in read only mode    */
  1111. X
  1112. X    /* check for negative repititions */
  1113. X    if (f && n < 0)
  1114. X        return(FALSE);
  1115. X
  1116. X    /* ask the user for the text of a pattern */
  1117. X    if ((s = readpattern(
  1118. X        (kind == FALSE ? "Replace" : "Query replace"))) != TRUE)
  1119. X        return(s);
  1120. X    strcpy(&tpat[0], &pat[0]);    /* salt it away */
  1121. X
  1122. X    /* ask for the replacement string */
  1123. X    strcpy(&pat[0], &rpat[0]);    /* set up default string */
  1124. X    if ((s = readpattern("with")) == ABORT)
  1125. X        return(s);
  1126. X
  1127. X    /* move everything to the right place and length them */
  1128. X    strcpy(&rpat[0], &pat[0]);
  1129. X    strcpy(&pat[0], &tpat[0]);
  1130. X    slength = strlen(&pat[0]);
  1131. X    rlength = strlen(&rpat[0]);
  1132. X
  1133. X    /* set up flags so we can make sure not to do a recursive
  1134. X       replace on the last line */
  1135. X    nlflag = (pat[slength - 1] == '\n');
  1136. X    nlrepl = FALSE;
  1137. X
  1138. X    /* build query replace question string */
  1139. X    strcpy(tpat, "Replace '");
  1140. X    expandp(&pat[0], &tpat[strlen(tpat)], NPAT/3);
  1141. X    strcat(tpat, "' with '");
  1142. X    expandp(&rpat[0], &tpat[strlen(tpat)], NPAT/3);
  1143. X    strcat(tpat, "'? ");
  1144. X
  1145. X    /* save original . position */
  1146. X    origline = curwp->w_dotp;
  1147. X    origoff = curwp->w_doto;
  1148. X
  1149. X    /* scan through the file */
  1150. X    numsub = 0;
  1151. X    nummatch = 0;
  1152. X    while ((f == FALSE || n > nummatch) &&
  1153. X        (nlflag == FALSE || nlrepl == FALSE)) {
  1154. X
  1155. X        /* search for the pattern */
  1156. X        if (forscan(&pat[0],PTBEG) != TRUE)
  1157. X            break;        /* all done */
  1158. X        ++nummatch;    /* increment # of matches */
  1159. X
  1160. X        /* check if we are on the last line */
  1161. X        nlrepl = (lforw(curwp->w_dotp) == curwp->w_bufp->b_linep);
  1162. X        
  1163. X        /* check for query */
  1164. X        if (kind) {
  1165. X            /* get the query */
  1166. X            mlwrite(&tpat[0], &pat[0], &rpat[0]);
  1167. Xqprompt:
  1168. X            update();  /* show the proposed place to change */
  1169. X            c = (*term.t_getchar)();    /* and input */
  1170. X            mlwrite("");            /* and clear it */
  1171. X
  1172. X            /* and respond appropriately */
  1173. X            switch (c) {
  1174. X                case 'y':    /* yes, substitute */
  1175. X                case ' ':
  1176. X                        break;
  1177. X
  1178. X                case 'n':    /* no, onword */
  1179. X                        forwchar(FALSE, 1);
  1180. X                        continue;
  1181. X
  1182. X                case '!':    /* yes/stop asking */
  1183. X                        kind = FALSE;
  1184. X                        break;
  1185. X
  1186. X                case '.':    /* abort! and return */
  1187. X                        /* restore old position */
  1188. X                        curwp->w_dotp = origline;
  1189. X                        curwp->w_doto = origoff;
  1190. X                        curwp->w_flag |= WFMOVE;
  1191. X
  1192. X                case BELL:    /* abort! and stay */
  1193. X                        mlwrite("Aborted!");
  1194. X                        return(FALSE);
  1195. X
  1196. X                default:    /* bitch and beep */
  1197. X                        (*term.t_beep)();
  1198. X
  1199. X                case '?':    /* help me */
  1200. Xmlwrite("(Y)es, (N)o, (!)Do the rest, (^G)Abort, (.)Abort back, (?)Help: ");
  1201. X                        goto qprompt;
  1202. X
  1203. X            }
  1204. X        }
  1205. X
  1206. X        /* delete the sucker */
  1207. X        if (ldelete(slength, FALSE) != TRUE) {
  1208. X            /* error while deleting */
  1209. X            mlwrite("ERROR while deleteing");
  1210. X            return(FALSE);
  1211. X        }
  1212. X
  1213. X        /* and insert its replacement */
  1214. X        for (i=0; i<rlength; i++) {
  1215. X            tmpc = rpat[i];
  1216. X            s = (tmpc == '\n' ? lnewline() : linsert(1, tmpc));
  1217. X            if (s != TRUE) {
  1218. X                /* error while inserting */
  1219. X                mlwrite("Out of memory while inserting");
  1220. X                return(FALSE);
  1221. X            }
  1222. X        }
  1223. X
  1224. X        numsub++;    /* increment # of substitutions */
  1225. X    }
  1226. X
  1227. X    /* and report the results */
  1228. X    mlwrite("%d substitutions",numsub);
  1229. X    return(TRUE);
  1230. X}
  1231. X
  1232. Xforscan(patrn,leavep)    /*    search forward for a <patrn>    */
  1233. X
  1234. Xchar *patrn;        /* string to scan for */
  1235. Xint leavep;        /* place to leave point
  1236. X                PTBEG = begining of match
  1237. X                PTEND = at end of match        */
  1238. X
  1239. X{
  1240. X    register LINE *curline;        /* current line during scan */
  1241. X    register int curoff;        /* position within current line */
  1242. X    register LINE *lastline;    /* last line position during scan */
  1243. X    register int lastoff;        /* position within last line */
  1244. X    register int c;            /* character at current position */
  1245. X    register LINE *matchline;    /* current line during matching */
  1246. X    register int matchoff;        /* position in matching line */
  1247. X    register char *patptr;        /* pointer into pattern */
  1248. X
  1249. X    /* setup local scan pointers to global "." */
  1250. X
  1251. X    curline = curwp->w_dotp;
  1252. X    curoff = curwp->w_doto;
  1253. X
  1254. X    /* scan each character until we hit the head link record */
  1255. X
  1256. X    while (curline != curbp->b_linep) {
  1257. X
  1258. X        /* save the current position in case we need to
  1259. X           restore it on a match            */
  1260. X
  1261. X        lastline = curline;
  1262. X        lastoff = curoff;
  1263. X
  1264. X        /* get the current character resolving EOLs */
  1265. X
  1266. X        if (curoff == llength(curline)) {    /* if at EOL */
  1267. X            curline = lforw(curline);    /* skip to next line */
  1268. X            curoff = 0;
  1269. X            c = '\n';            /* and return a <NL> */
  1270. X        } else
  1271. X            c = lgetc(curline, curoff++);    /* get the char */
  1272. X
  1273. X        /* test it against first char in pattern */
  1274. X        if (eq(c, patrn[0]) != FALSE) {    /* if we find it..*/
  1275. X            /* setup match pointers */
  1276. X            matchline = curline;
  1277. X            matchoff = curoff;
  1278. X            patptr = &patrn[0];
  1279. X
  1280. X            /* scan through patrn for a match */
  1281. X            while (*++patptr != 0) {
  1282. X                /* advance all the pointers */
  1283. X                if (matchoff == llength(matchline)) {
  1284. X                    /* advance past EOL */
  1285. X                    matchline = lforw(matchline);
  1286. X                    matchoff = 0;
  1287. X                    c = '\n';
  1288. X                } else
  1289. X                    c = lgetc(matchline, matchoff++);
  1290. X
  1291. X                /* and test it against the pattern */
  1292. X                if (eq(*patptr, c) == FALSE)
  1293. X                    goto fail;
  1294. X            }
  1295. X
  1296. X            /* A SUCCESSFULL MATCH!!! */
  1297. X            /* reset the global "." pointers */
  1298. X            if (leavep == PTEND) {    /* at end of string */
  1299. X                curwp->w_dotp = matchline;
  1300. X                curwp->w_doto = matchoff;
  1301. X            } else {        /* at begining of string */
  1302. X                curwp->w_dotp = lastline;
  1303. X                curwp->w_doto = lastoff;
  1304. X            }
  1305. X            curwp->w_flag |= WFMOVE; /* flag that we have moved */
  1306. X            return(TRUE);
  1307. X
  1308. X        }
  1309. Xfail:;            /* continue to search */
  1310. X    }
  1311. X
  1312. X    /* we could not find a match */
  1313. X
  1314. X    return(FALSE);
  1315. X}
  1316. X
  1317. X/*     expandp:    expand control key sequences for output        */
  1318. X
  1319. Xexpandp(srcstr, deststr, maxlength)
  1320. X
  1321. Xchar *srcstr;    /* string to expand */
  1322. Xchar *deststr;    /* destination of expanded string */
  1323. Xint maxlength;    /* maximum chars in destination */
  1324. X
  1325. X{
  1326. X    char c;        /* current char to translate */
  1327. X
  1328. X    /* scan through the string */
  1329. X    while ((c = *srcstr++) != 0) {
  1330. X        if (c == '\n') {        /* its an EOL */
  1331. X            *deststr++ = '<';
  1332. X            *deststr++ = 'N';
  1333. X            *deststr++ = 'L';
  1334. X            *deststr++ = '>';
  1335. X            maxlength -= 4;
  1336. X        } else if (c < 0x20 || c == 0x7f) {    /* control character */
  1337. X            *deststr++ = '^';
  1338. X            *deststr++ = c ^ 0x40;
  1339. X            maxlength -= 2;
  1340. X        } else if (c == '%') {
  1341. X            *deststr++ = '%';
  1342. X            *deststr++ = '%';
  1343. X            maxlength -= 2;
  1344. X
  1345. X        } else {            /* any other character */
  1346. X            *deststr++ = c;
  1347. X            maxlength--;
  1348. X        }
  1349. X
  1350. X        /* check for maxlength */
  1351. X        if (maxlength < 4) {
  1352. X            *deststr++ = '$';
  1353. X            *deststr = '\0';
  1354. X            return(FALSE);
  1355. X        }
  1356. X    }
  1357. X    *deststr = '\0';
  1358. X    return(TRUE);
  1359. X}
  1360. *-*-END-of-search.c-*-*
  1361. echo x - spawn.c
  1362. sed 's/^X//' >spawn.c <<'*-*-END-of-spawn.c-*-*'
  1363. X/*
  1364. X * The routines in this file are called to create a subjob running a command
  1365. X * interpreter. This code is a big fat nothing on CP/M-86. You lose.
  1366. X */
  1367. X#include        <stdio.h>
  1368. X#include    "estruct.h"
  1369. X#include        "edef.h"
  1370. X
  1371. X#if     AMIGA
  1372. X#define  NEW   1006
  1373. X#endif
  1374. X
  1375. X#if     VMS
  1376. X#define EFN     0                               /* Event flag.          */
  1377. X
  1378. X#include        <ssdef.h>                       /* Random headers.      */
  1379. X#include        <stsdef.h>
  1380. X#include        <descrip.h>
  1381. X#include        <iodef.h>
  1382. X
  1383. Xextern  int     oldmode[];                      /* In "termio.c"        */
  1384. Xextern  int     newmode[];                      /* In "termio.c"        */
  1385. Xextern  short   iochan;                         /* In "termio.c"        */
  1386. X#endif
  1387. X
  1388. X#if     MSDOS & LATTICE
  1389. X#include        <dos.h>
  1390. X#undef    CPM
  1391. X#endif
  1392. X
  1393. X#if     V7
  1394. X#include        <signal.h>
  1395. Xextern int vttidy();
  1396. X#endif
  1397. X
  1398. X/*
  1399. X * Create a subjob with a copy of the command intrepreter in it. When the
  1400. X * command interpreter exits, mark the screen as garbage so that you do a full
  1401. X * repaint. Bound to "^X C". The message at the start in VMS puts out a newline.
  1402. X * Under some (unknown) condition, you don't get one free when DCL starts up.
  1403. X */
  1404. Xspawncli(f, n)
  1405. X{
  1406. X#if     AMIGA
  1407. X        long newcli;
  1408. X
  1409. X        newcli = Open("CON:1/1/639/199/MicroEmacs Subprocess", NEW);
  1410. X        mlwrite("[Starting new CLI]");
  1411. X        sgarbf = TRUE;
  1412. X        Execute("", newcli, 0);
  1413. X        Close(newcli);
  1414. X        return(TRUE);
  1415. X#endif
  1416. X
  1417. X#if     V7
  1418. X        register char *cp;
  1419. X        char    *getenv();
  1420. X#endif
  1421. X#if     VMS
  1422. X        movecursor(term.t_nrow, 0);             /* In last line.        */
  1423. X        mlputs("[Starting DCL]\r\n");
  1424. X        (*term.t_flush)();                      /* Ignore "ttcol".      */
  1425. X        sgarbf = TRUE;
  1426. X        return (sys(NULL));                     /* NULL => DCL.         */
  1427. X#endif
  1428. X#if     CPM
  1429. X        mlwrite("Not in CP/M-86");
  1430. X#endif
  1431. X#if     MSDOS & AZTEC
  1432. X        movecursor(term.t_nrow, 0);             /* Seek to last line.   */
  1433. X        (*term.t_flush)();
  1434. X    system("command.com");
  1435. X        sgarbf = TRUE;
  1436. X        return(TRUE);
  1437. X#endif
  1438. X#if     MSDOS & LATTICE
  1439. X        movecursor(term.t_nrow, 0);             /* Seek to last line.   */
  1440. X        (*term.t_flush)();
  1441. X        sys("\\command.com", "");               /* Run CLI.             */
  1442. X        sgarbf = TRUE;
  1443. X        return(TRUE);
  1444. X#endif
  1445. X#if     V7
  1446. X        movecursor(term.t_nrow, 0);             /* Seek to last line.   */
  1447. X        (*term.t_flush)();
  1448. X        ttclose();                              /* stty to old settings */
  1449. X        if ((cp = getenv("SHELL")) != NULL && *cp != '\0')
  1450. X                system(cp);
  1451. X        else
  1452. X#if    BSD
  1453. X                system("exec /bin/csh");
  1454. X#else
  1455. X                system("exec /bin/sh");
  1456. X#endif
  1457. X        sgarbf = TRUE;
  1458. X        sleep(2);
  1459. X        ttopen();
  1460. X        return(TRUE);
  1461. X#endif
  1462. X}
  1463. X
  1464. X#if    V7 & BSD
  1465. X
  1466. Xbktoshell()        /* suspend MicroEMACS and wait to wake up */
  1467. X{
  1468. X    int pid;
  1469. X
  1470. X    vttidy();
  1471. X    pid = getpid();
  1472. X    kill(pid,SIGTSTP);
  1473. X}
  1474. X
  1475. Xrtfrmshell()
  1476. X{
  1477. X    ttopen();
  1478. X    curwp->w_flag = WFHARD;
  1479. X    refresh();
  1480. X}
  1481. X#endif
  1482. X
  1483. X/*
  1484. X * Run a one-liner in a subjob. When the command returns, wait for a single
  1485. X * character to be typed, then mark the screen as garbage so a full repaint is
  1486. X * done. Bound to "C-X !".
  1487. X */
  1488. Xspawn(f, n)
  1489. X{
  1490. X        register int    s;
  1491. X        char            line[NLINE];
  1492. X#if     AMIGA
  1493. X        long newcli;
  1494. X
  1495. X        newcli = Open("CON:1/1/639/199/MicroEmacs Subprocess", NEW);
  1496. X        if ((s=mlreply("CLI command: ", line, NLINE)) != TRUE)
  1497. X                return (s);
  1498. X        Execute(line,0,newcli);
  1499. X        Close(newcli);
  1500. X        (*term.t_getchar)();     /* Pause.               */
  1501. X        sgarbf = TRUE;
  1502. X        return(TRUE);
  1503. X#endif
  1504. X#if     VMS
  1505. X        if ((s=mlreply("DCL command: ", line, NLINE)) != TRUE)
  1506. X                return (s);
  1507. X        (*term.t_putchar)('\n');                /* Already have '\r'    */
  1508. X        (*term.t_flush)();
  1509. X        s = sys(line);                          /* Run the command.     */
  1510. X        mlputs("\r\n\n[End]");                  /* Pause.               */
  1511. X        (*term.t_flush)();
  1512. X        (*term.t_getchar)();
  1513. X        sgarbf = TRUE;
  1514. X        return (s);
  1515. X#endif
  1516. X#if     CPM
  1517. X        mlwrite("Not in CP/M-86");
  1518. X        return (FALSE);
  1519. X#endif
  1520. X#if     MSDOS
  1521. X        if ((s=mlreply("MS-DOS command: ", line, NLINE)) != TRUE)
  1522. X                return (s);
  1523. X        system(line);
  1524. X        mlputs("\r\n\n[End]");                  /* Pause.               */
  1525. X        (*term.t_getchar)();     /* Pause.               */
  1526. X        sgarbf = TRUE;
  1527. X        return (TRUE);
  1528. X#endif
  1529. X#if     V7
  1530. X        if ((s=mlreply("! ", line, NLINE)) != TRUE)
  1531. X                return (s);
  1532. X        (*term.t_putchar)('\n');                /* Already have '\r'    */
  1533. X        (*term.t_flush)();
  1534. X        ttclose();                              /* stty to old modes    */
  1535. X        system(line);
  1536. X        sleep(2);
  1537. X        ttopen();
  1538. X        mlputs("[End]");                        /* Pause.               */
  1539. X        (*term.t_flush)();
  1540. X        while ((s = (*term.t_getchar)()) != '\r' && s != ' ')
  1541. X                ;
  1542. X        sgarbf = TRUE;
  1543. X        return (TRUE);
  1544. X#endif
  1545. X}
  1546. X
  1547. X#if     VMS
  1548. X/*
  1549. X * Run a command. The "cmd" is a pointer to a command string, or NULL if you
  1550. X * want to run a copy of DCL in the subjob (this is how the standard routine
  1551. X * LIB$SPAWN works. You have to do wierd stuff with the terminal on the way in
  1552. X * and the way out, because DCL does not want the channel to be in raw mode.
  1553. X */
  1554. Xsys(cmd)
  1555. Xregister char   *cmd;
  1556. X{
  1557. X        struct  dsc$descriptor  cdsc;
  1558. X        struct  dsc$descriptor  *cdscp;
  1559. X        long    status;
  1560. X        long    substatus;
  1561. X        long    iosb[2];
  1562. X
  1563. X        status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
  1564. X                          oldmode, sizeof(oldmode), 0, 0, 0, 0);
  1565. X        if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
  1566. X                return (FALSE);
  1567. X        cdscp = NULL;                           /* Assume DCL.          */
  1568. X        if (cmd != NULL) {                      /* Build descriptor.    */
  1569. X                cdsc.dsc$a_pointer = cmd;
  1570. X                cdsc.dsc$w_length  = strlen(cmd);
  1571. X                cdsc.dsc$b_dtype   = DSC$K_DTYPE_T;
  1572. X                cdsc.dsc$b_class   = DSC$K_CLASS_S;
  1573. X                cdscp = &cdsc;
  1574. X        }
  1575. X        status = LIB$SPAWN(cdscp, 0, 0, 0, 0, 0, &substatus, 0, 0, 0);
  1576. X        if (status != SS$_NORMAL)
  1577. X                substatus = status;
  1578. X        status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
  1579. X                          newmode, sizeof(newmode), 0, 0, 0, 0);
  1580. X        if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
  1581. X                return (FALSE);
  1582. X        if ((substatus&STS$M_SUCCESS) == 0)     /* Command failed.      */
  1583. X                return (FALSE);
  1584. X        return (TRUE);
  1585. X}
  1586. X#endif
  1587. X
  1588. X#if    ~AZTEC & MSDOS
  1589. X
  1590. X/*
  1591. X * This routine, once again by Bob McNamara, is a C translation of the "system"
  1592. X * routine in the MWC-86 run time library. It differs from the "system" routine
  1593. X * in that it does not unconditionally append the string ".exe" to the end of
  1594. X * the command name. We needed to do this because we want to be able to spawn
  1595. X * off "command.com". We really do not understand what it does, but if you don't
  1596. X * do it exactly "malloc" starts doing very very strange things.
  1597. X */
  1598. Xsys(cmd, tail)
  1599. Xchar    *cmd;
  1600. Xchar    *tail;
  1601. X{
  1602. X#if MWC_86
  1603. X        register unsigned n;
  1604. X        extern   char     *__end;
  1605. X
  1606. X        n = __end + 15;
  1607. X        n >>= 4;
  1608. X        n = ((n + dsreg() + 16) & 0xFFF0) + 16;
  1609. X        return(execall(cmd, tail, n));
  1610. X#endif
  1611. X
  1612. X#if LATTICE
  1613. X        return forklp(cmd, tail, NULL);
  1614. X#endif
  1615. X}
  1616. X#endif
  1617. *-*-END-of-spawn.c-*-*
  1618. echo x - tcap.c
  1619. sed 's/^X//' >tcap.c <<'*-*-END-of-tcap.c-*-*'
  1620. X/*    tcap:    Unix V5, V7 and BS4.2 Termcap video driver
  1621. X        for MicroEMACS
  1622. X*/
  1623. X
  1624. X#define    termdef    1            /* don't define "term" external */
  1625. X
  1626. X#include <stdio.h>
  1627. X#include    "estruct.h"
  1628. X#include        "edef.h"
  1629. X
  1630. X#if TERMCAP
  1631. X
  1632. X#define NROW    24
  1633. X#define NCOL    80
  1634. X#define    MARGIN    8
  1635. X#define    SCRSIZ    64
  1636. X#define BEL     0x07
  1637. X#define ESC     0x1B
  1638. X
  1639. Xextern int      ttopen();
  1640. Xextern int      ttgetc();
  1641. Xextern int      ttputc();
  1642. Xextern int      ttflush();
  1643. Xextern int      ttclose();
  1644. Xextern int      tcapmove();
  1645. Xextern int      tcapeeol();
  1646. Xextern int      tcapeeop();
  1647. Xextern int      tcapbeep();
  1648. Xextern int    tcaprev();
  1649. Xextern int      tcapopen();
  1650. Xextern int      tput();
  1651. Xextern char     *tgoto();
  1652. X
  1653. X#define TCAPSLEN 315
  1654. Xchar tcapbuf[TCAPSLEN];
  1655. Xchar *UP, PC, *CM, *CE, *CL, *SO, *SE;
  1656. X
  1657. XTERM term = {
  1658. X        NROW-1,
  1659. X        NCOL,
  1660. X    MARGIN,
  1661. X    SCRSIZ,
  1662. X        tcapopen,
  1663. X        ttclose,
  1664. X        ttgetc,
  1665. X        ttputc,
  1666. X        ttflush,
  1667. X        tcapmove,
  1668. X        tcapeeol,
  1669. X        tcapeeop,
  1670. X        tcapbeep,
  1671. X        tcaprev
  1672. X};
  1673. X
  1674. Xtcapopen()
  1675. X
  1676. X{
  1677. X        char *getenv();
  1678. X        char *t, *p, *tgetstr();
  1679. X        char tcbuf[1024];
  1680. X        char *tv_stype;
  1681. X        char err_str[72];
  1682. X
  1683. X        if ((tv_stype = getenv("TERM")) == NULL)
  1684. X        {
  1685. X                puts("Environment variable TERM not defined!");
  1686. X                exit(1);
  1687. X        }
  1688. X
  1689. X        if((tgetent(tcbuf, tv_stype)) != 1)
  1690. X        {
  1691. X                sprintf(err_str, "Unknown terminal type %s!", tv_stype);
  1692. X                puts(err_str);
  1693. X                exit(1);
  1694. X        }
  1695. X
  1696. X        p = tcapbuf;
  1697. X        t = tgetstr("pc", &p);
  1698. X        if(t)
  1699. X                PC = *t;
  1700. X
  1701. X        CL = tgetstr("cl", &p);
  1702. X        CM = tgetstr("cm", &p);
  1703. X        CE = tgetstr("ce", &p);
  1704. X        UP = tgetstr("up", &p);
  1705. X    SE = tgetstr("se", &p);
  1706. X    SO = tgetstr("so", &p);
  1707. X    if (SO != NULL)
  1708. X        revexist = TRUE;
  1709. X
  1710. X        if(CL == NULL || CM == NULL || UP == NULL)
  1711. X        {
  1712. X                puts("Incomplete termcap entry\n");
  1713. X                exit(1);
  1714. X        }
  1715. X
  1716. X    if (CE == NULL)        /* will we be able to use clear to EOL? */
  1717. X        eolexist = FALSE;
  1718. X        
  1719. X        if (p >= &tcapbuf[TCAPSLEN])
  1720. X        {
  1721. X                puts("Terminal description too big!\n");
  1722. X                exit(1);
  1723. X        }
  1724. X        ttopen();
  1725. X}
  1726. X
  1727. Xtcapmove(row, col)
  1728. Xregister int row, col;
  1729. X{
  1730. X        putpad(tgoto(CM, col, row));
  1731. X}
  1732. X
  1733. Xtcapeeol()
  1734. X{
  1735. X        putpad(CE);
  1736. X}
  1737. X
  1738. Xtcapeeop()
  1739. X{
  1740. X        putpad(CL);
  1741. X}
  1742. X
  1743. Xtcaprev(state)        /* change reverse video status */
  1744. X
  1745. Xint state;    /* FALSE = normal video, TRUE = reverse video */
  1746. X
  1747. X{
  1748. X    if (state) {
  1749. X        if (SO != NULL)
  1750. X            putpad(SO);
  1751. X    } else {
  1752. X        if (SE != NULL)
  1753. X            putpad(SE);
  1754. X    }
  1755. X}
  1756. X
  1757. Xtcapbeep()
  1758. X{
  1759. X        ttputc(BEL);
  1760. X}
  1761. X
  1762. Xputpad(str)
  1763. Xchar    *str;
  1764. X{
  1765. X        tputs(str, 1, ttputc);
  1766. X}
  1767. X
  1768. Xputnpad(str, n)
  1769. Xchar    *str;
  1770. X{
  1771. X        tputs(str, n, ttputc);
  1772. X}
  1773. X
  1774. X#else
  1775. X
  1776. Xhello()
  1777. X{
  1778. X}
  1779. X
  1780. X#endif TERMCAP
  1781. *-*-END-of-tcap.c-*-*
  1782. exit
  1783.  
  1784.  
  1785.