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

  1. Subject: v06i076:  MicroEmacs, Version 3.7 (uEmacs3.7), Part06/12
  2. Newsgroups: mod.sources
  3. Approved: rs@mirror.UUCP
  4.  
  5. Submitted by: ihnp4!pur-ee!pur-phy!duncan!lawrence
  6. Mod.sources: Volume 6, Issue 76
  7. Archive-name: uEmacs3.7/Part06
  8.  
  9. [  This is the latest revision of one of two programs named "MicroEmacs";
  10.    when discussing these on the net, or in contacting the authors, make
  11.    sure to mention the version number -- in this case 3.7 -- as that is
  12.    the easiest way to distinguish between them.  Daniel will be posting
  13.    uuencoded executables in net.micro.pc and net.micro.amiga; the file
  14.    'readme' contains information on how to also get these from him
  15.    directly.   --r$ ]
  16.  
  17. echo extracting - fileio.c
  18. sed 's/^X//' > fileio.c << 'FRIDAY_NIGHT'
  19. X/*
  20. X * The routines in this file read and write ASCII files from the disk. All of
  21. X * the knowledge about files are here. A better message writing scheme should
  22. X * be used.
  23. X */
  24. X#include        <stdio.h>
  25. X#include    "estruct.h"
  26. X#include        "edef.h"
  27. X
  28. XFILE    *ffp;                           /* File pointer, all functions. */
  29. X
  30. X/*
  31. X * Open a file for reading.
  32. X */
  33. Xffropen(fn)
  34. Xchar    *fn;
  35. X{
  36. X        if ((ffp=fopen(fn, "r")) == NULL)
  37. X                return (FIOFNF);
  38. X        return (FIOSUC);
  39. X}
  40. X
  41. X/*
  42. X * Open a file for writing. Return TRUE if all is well, and FALSE on error
  43. X * (cannot create).
  44. X */
  45. Xffwopen(fn)
  46. Xchar    *fn;
  47. X{
  48. X#if     VMS
  49. X        register int    fd;
  50. X
  51. X        if ((fd=creat(fn, 0666, "rfm=var", "rat=cr")) < 0
  52. X        || (ffp=fdopen(fd, "w")) == NULL) {
  53. X#else
  54. X        if ((ffp=fopen(fn, "w")) == NULL) {
  55. X#endif
  56. X                mlwrite("Cannot open file for writing");
  57. X                return (FIOERR);
  58. X        }
  59. X        return (FIOSUC);
  60. X}
  61. X
  62. X/*
  63. X * Close a file. Should look at the status in all systems.
  64. X */
  65. Xffclose()
  66. X{
  67. X#if    MSDOS
  68. X    fputc(26, ffp);        /* add a ^Z at the end of the file */
  69. X#endif
  70. X    
  71. X#if     V7 | USG | BSD | (MSDOS & (LATTICE | MSC))
  72. X        if (fclose(ffp) != FALSE) {
  73. X                mlwrite("Error closing file");
  74. X                return(FIOERR);
  75. X        }
  76. X        return(FIOSUC);
  77. X#else
  78. X        fclose(ffp);
  79. X        return (FIOSUC);
  80. X#endif
  81. X}
  82. X
  83. X/*
  84. X * Write a line to the already opened file. The "buf" points to the buffer,
  85. X * and the "nbuf" is its length, less the free newline. Return the status.
  86. X * Check only at the newline.
  87. X */
  88. Xffputline(buf, nbuf)
  89. Xchar    buf[];
  90. X{
  91. X        register int    i;
  92. X
  93. X        for (i = 0; i < nbuf; ++i)
  94. X                fputc(buf[i]&0xFF, ffp);
  95. X
  96. X        fputc('\n', ffp);
  97. X
  98. X        if (ferror(ffp)) {
  99. X                mlwrite("Write I/O error");
  100. X                return (FIOERR);
  101. X        }
  102. X
  103. X        return (FIOSUC);
  104. X}
  105. X
  106. X/*
  107. X * Read a line from a file, and store the bytes in the supplied buffer. The
  108. X * "nbuf" is the length of the buffer. Complain about long lines and lines
  109. X * at the end of the file that don't have a newline present. Check for I/O
  110. X * errors too. Return status.
  111. X */
  112. Xffgetline(buf, nbuf)
  113. Xregister char   buf[];
  114. X{
  115. X        register int    c;
  116. X        register int    i;
  117. X
  118. X        i = 0;
  119. X
  120. X        while ((c = fgetc(ffp)) != EOF && c != '\n') {
  121. X                if (i >= nbuf-2) {
  122. X            buf[nbuf - 2] = c;    /* store last char read */
  123. X            buf[nbuf - 1] = 0;    /* and terminate it */
  124. X                        mlwrite("File has long line");
  125. X                        return (FIOLNG);
  126. X                }
  127. X                buf[i++] = c;
  128. X        }
  129. X
  130. X        if (c == EOF) {
  131. X                if (ferror(ffp)) {
  132. X                        mlwrite("File read error");
  133. X                        return (FIOERR);
  134. X                }
  135. X
  136. X                if (i != 0) {
  137. X                        mlwrite("File has funny line at EOF");
  138. X                        return (FIOERR);
  139. X                }
  140. X                return (FIOEOF);
  141. X        }
  142. X
  143. X        buf[i] = 0;
  144. X        return (FIOSUC);
  145. X}
  146. FRIDAY_NIGHT
  147. echo extracting - hp150.c
  148. sed 's/^X//' > hp150.c << 'FRIDAY_NIGHT'
  149. X/*
  150. X * The routines in this file provide support for HP150 screens
  151. X * and routines to access the Keyboard through KEYCODE mode.
  152. X * It compiles into nothing if not an HP150 screen device.
  153. X * added by Daniel Lawrence
  154. X */
  155. X
  156. X#define    termdef    1            /* don't define "term" external */
  157. X
  158. X#include        <stdio.h>
  159. X#include        "estruct.h"
  160. X#include    "edef.h"
  161. X
  162. X#if     HP150
  163. X
  164. X#define NROW    24                      /* Screen size.                 */
  165. X#define NCOL    80                      /* Edit if you want to.         */
  166. X#define    MARGIN    8            /* size of minimim margin and    */
  167. X#define    SCRSIZ    64            /* scroll size for extended lines */
  168. X#define    NPAUSE    15            /* # times thru update to pause */
  169. X#define BEL     0x07                    /* BEL character.               */
  170. X#define ESC     0x1B                    /* ESC character.               */
  171. X
  172. Xextern  int     openhp();               /* Forward references.          */
  173. Xextern  int     ttgetc();
  174. Xextern  int     ttputc();
  175. Xextern  int     ttflush();
  176. Xextern    int    hpflush();
  177. Xextern  int     closehp();
  178. Xextern  int     hp15move();
  179. Xextern  int     hp15eeol();
  180. Xextern  int     hp15eeop();
  181. Xextern  int     hp15beep();
  182. Xextern    int    gethpkey();
  183. Xextern    int    hp15rev();
  184. X#if    COLOR
  185. Xextern    int    hp15fcol();
  186. Xextern    int    hp15bcol();
  187. X#endif
  188. X
  189. X/* weird to ascii translation table */
  190. X
  191. Xchar trans[][2] = {
  192. X    0x24,    9,    /* tab */
  193. X    0x25,    13,    /* ret */
  194. X    0x27,    8,    /* backspace */
  195. X    0x30,    48,    /* zero */
  196. X    0x31,    49,    /* one */
  197. X    0x32,    50,    /* two */
  198. X    0x33,    51,    /* three */
  199. X    0x34,    52,    /* four */
  200. X    0x35,    53,    /* five */
  201. X    0x36,    54,    /* six */
  202. X    0x37,    55,    /* seven */
  203. X    0x38,    56,    /* eight */
  204. X    0x39,    57,    /* nine */
  205. X    0x50,    13,    /* enter */
  206. X    0x54,    27,    /* break -> ESC */
  207. X    0x55,    27,    /* esc */
  208. X    0x58,    24,    /* stop -> ^X */
  209. X    0x70,    45,    /* N-minus */
  210. X    0x71,    42,    /* N-asterisk */
  211. X    0x72,    43,    /* N-plus */
  212. X    0x73,    47,    /* N-slash */
  213. X    0x74,    44,    /* N-comma */
  214. X    0x75,    13,    /* N-enter */
  215. X    0x76,    9,    /* N-tab */
  216. X    0x77,    46    /* N-period */
  217. X};
  218. X
  219. X#define NTRANS    sizeof(trans) / 2
  220. X
  221. Xunion REGS r;        /* register set for bios and dos (AGIOS) calls */
  222. Xint capslock = 0;    /* caps lock flag */
  223. X
  224. X/*
  225. X * Standard terminal interface dispatch table. Most of the fields point into
  226. X * "termio" code.
  227. X */
  228. XTERM    term    = {
  229. X        NROW-1,
  230. X        NCOL,
  231. X    MARGIN,
  232. X    SCRSIZ,
  233. X    NPAUSE,
  234. X    openhp,
  235. X        closehp,
  236. X    gethpkey,
  237. X        ttputc,
  238. X        hpflush,
  239. X        hp15move,
  240. X        hp15eeol,
  241. X        hp15eeop,
  242. X        hp15beep,
  243. X        hp15rev
  244. X#if    COLOR
  245. X    , hp15fcol,
  246. X    hp15bcol
  247. X#endif
  248. X};
  249. X
  250. Xhp15move(row, col)
  251. X{
  252. X        ttputc(ESC);
  253. X        ttputc('&');
  254. X        ttputc('a');
  255. X        hp15parm(col);
  256. X        ttputc('c');
  257. X        hp15parm(row);
  258. X        ttputc('R');
  259. X}
  260. X
  261. Xhpflush()
  262. X
  263. X{
  264. X
  265. X}
  266. X
  267. Xhp15eeol()
  268. X{
  269. X        ttputc(ESC);
  270. X        ttputc('K');
  271. X}
  272. X
  273. Xhp15eeop()
  274. X{
  275. X        ttputc(ESC);
  276. X        ttputc('J');
  277. X}
  278. X
  279. Xhp15rev(status)        /* change the reverse video status */
  280. X
  281. Xint status;    /* TRUE = on, FALSE = off */
  282. X
  283. X{
  284. X    ttputc(ESC);
  285. X    ttputc('&');
  286. X    ttputc('d');
  287. X    ttputc(status ? 'B': '@');
  288. X}
  289. X
  290. Xhp15beep()
  291. X{
  292. X        ttputc(BEL);
  293. X        ttflush();
  294. X}
  295. X
  296. Xhp15parm(n)
  297. Xregister int    n;
  298. X{
  299. X        register int    q;
  300. X
  301. X        q = n/10;
  302. X        if (q != 0)
  303. X                hp15parm(q);
  304. X        ttputc((n%10) + '0');
  305. X}
  306. X
  307. X#if    COLOR
  308. Xhp15fcol()    /* we really can't do colors here, so just ignore it */
  309. X{
  310. X}
  311. X
  312. Xhp15bcol()    /* we really can't do colors here, so just ignore it */
  313. X{
  314. X}
  315. X#endif
  316. X
  317. Xgethpkey()    /* get a key from the HP keyboard while in keycode mode */
  318. X
  319. X{
  320. X    static int keepflag = 0;    /* kept ahead char flag */
  321. X    static int keepchar = 0;    /* kept ehead flag */
  322. X    int c;
  323. X    int devid;            /* device ID */
  324. X    int ctype;            /* type of character gotten */
  325. X    int shiftb;            /* state of shift keys */
  326. X    int i;
  327. X    
  328. X    /* if we are in an extended char sequence, finish it */
  329. X    if (keepflag != 0) {
  330. X        keepflag = 0;
  331. X        return(keepchar);
  332. X    }
  333. X
  334. X    /* grab the next 4 char sequence */
  335. Xnext:    shiftb = ttgetc();
  336. X    devid = ttgetc();
  337. X    c = ttgetc();
  338. X    ttgetc();        /* skip null byte */
  339. X    
  340. X    /* make sure we are from the keyboard */
  341. X    if (devid != 192)
  342. X        goto next;
  343. X
  344. X    /* if normal ascii, return it */
  345. X    if ((shiftb & 0x80) == 0) {
  346. X        if (capslock && c >= 'a' && c <= 'z')
  347. X            c -= 32;
  348. X        return(c);
  349. X    }
  350. X
  351. X    /* check specifically for the caps lock key */
  352. X    if (c == 0x56) {
  353. X        capslock = ~capslock;
  354. X        goto next;
  355. X    }
  356. X
  357. X    /* check to see if it needs translation */
  358. X    for (i=0; i < NTRANS; i++)
  359. X        if (trans[i][0] == c)
  360. X            return((int)trans[i][1]);
  361. X
  362. X    /* other wise, shove it in the keep char and return the leadin code */
  363. X    keepchar = c;
  364. X    keepflag = 1;
  365. X    return(0);
  366. X}
  367. X
  368. Xopenhp()        /* open the HP150 keyboard for input */
  369. X
  370. X{
  371. X    revexist = TRUE;
  372. X
  373. X    /* define key charectoristics with AGIOS call (0, 40) */
  374. X    defkey();
  375. X
  376. X    /* Turn on RAW mode with MSDOS call 44h */
  377. X    rawon();
  378. X
  379. X    /* Turn off Control-C checking  MS-DOS 33h */
  380. X    ckeyoff();
  381. X
  382. X    /* Turn on keycode mode with AGIOS call (0,43) */
  383. X    keycon();
  384. X}
  385. X
  386. Xclosehp()        /* close the HP150 keyboard for input */
  387. X
  388. X{
  389. X    /* define key charectoristics with AGIOS call (0, 40) */
  390. X    undefkey();
  391. X    
  392. X    /* Turn off RAW mode with MSDOS call 44h */
  393. X    rawoff();
  394. X
  395. X    /* Turn on Control-C checking  MS-DOS 33h */
  396. X    ckeyon();
  397. X
  398. X    /* Turn off keycode mode with AGIOS call (0,43) */
  399. X    keycoff();
  400. X}
  401. X
  402. Xrawon()        /* put the HP150 keyboard into RAW mode */
  403. X
  404. X{
  405. X    /* get the IO control info */
  406. X
  407. X    r.x.ax = 0x4400;    /* IO ctrl get device information */
  408. X    r.x.bx = 0x0001;    /* File handle; 1 for console */
  409. X    intdos(&r, &r);        /* go fer it */
  410. X
  411. X    r.h.dh = 0;        /* clear high byte for put */
  412. X    r.h.dl |= 0x20;        /* set raw bit */
  413. X
  414. X    /* and put it back */
  415. X
  416. X    r.x.ax = 0x4401;    /* IO ctrl put device information */
  417. X    r.x.bx = 0x0001;    /* File handle; 1 for console */
  418. X    intdos(&r, &r);        /* go fer it */
  419. X}
  420. X
  421. Xrawoff()    /* put the HP150 keyboard into COOKED mode */
  422. X
  423. X{
  424. X    /* get the IO control info */
  425. X
  426. X    r.x.ax = 0x4400;    /* IO ctrl get device information */
  427. X    r.x.bx = 0x0001;    /* File handle; 1 for console */
  428. X    intdos(&r, &r);        /* go fer it */
  429. X
  430. X    r.h.dh = 0;        /* clear high byte for put */
  431. X    r.h.dl &= 0xdf;        /* set raw bit */
  432. X
  433. X    /* and put it back */
  434. X
  435. X    r.x.ax = 0x4401;    /* IO ctrl put device information */
  436. X    r.x.bx = 0x0001;    /* File handle; 1 for console */
  437. X    intdos(&r, &r);        /* go fer it */
  438. X}
  439. X
  440. X
  441. Xckeyoff()    /* turn control-C trapping off */
  442. X
  443. X{
  444. X    r.h.ah = 0x33;    /* ctrl-break check */
  445. X    r.h.al = 1;    /* set the state of the ctrl-break check */
  446. X    r.h.dl = 0;    /* turn it off */
  447. X    intdos(&r, &r);
  448. X}
  449. X
  450. Xckeyon()    /* turn control-C trapping on */
  451. X
  452. X{
  453. X    r.h.ah = 0x33;    /* ctrl-break check */
  454. X    r.h.al = 1;    /* set the state of the ctrl-break check */
  455. X    r.h.dl = 1;    /* turn it on */
  456. X    intdos(&r, &r);
  457. X}
  458. X
  459. Xagios(buf, len)    /* perform an AGIOS call */
  460. X
  461. Xchar *buf;    /* sequence of bytes in command */
  462. Xint len;    /* length of command in bytes */
  463. X
  464. X{
  465. X    r.x.ax = 0x4403;    /* I/O ctrl write */
  466. X    r.x.bx = 1;        /* console handle */
  467. X    r.x.cx = len;        /* buffer length */
  468. X    r.x.dx = (unsigned)buf;    /* buffer address */
  469. X    return(intdos(&r, &r));    /* do it */
  470. X}
  471. X
  472. Xkeycon()    /* turn keycode mode on */
  473. X
  474. X{
  475. X    static char cmd[] = {43, 0, 1};
  476. X
  477. X    return(agios(&cmd[0], 3));
  478. X}
  479. X
  480. Xkeycoff()    /* turn keycode mode off */
  481. X
  482. X{
  483. X    static char cmd[] = {43, 0, 0};
  484. X
  485. X    return(agios(&cmd[0], 3));
  486. X}
  487. X
  488. Xdefkey()    /* change all special keys to intercept mode */
  489. X
  490. X{
  491. X    static char cmd[] = {40, 0, 2, 0, 0xfe, 0};
  492. X
  493. X    return(agios(&cmd[0], 6));
  494. X}
  495. X
  496. Xundefkey()    /* change all special keys to intercept mode */
  497. X
  498. X{
  499. X    static char cmd[] = {40, 0, 0, 0, 0xfe, 0};
  500. X
  501. X    return(agios(&cmd[0], 6));
  502. X}
  503. X
  504. X#else
  505. X
  506. Xh15hello()
  507. X
  508. X{
  509. X}
  510. X#endif
  511. FRIDAY_NIGHT
  512. echo extracting - ibmpc.c
  513. sed 's/^X//' > ibmpc.c << 'FRIDAY_NIGHT'
  514. X/*
  515. X * The routines in this file provide support for the IBM-PC and other
  516. X * compatible terminals. It goes directly to the graphics RAM to do
  517. X * screen output. It compiles into nothing if not an IBM-PC driver
  518. X */
  519. X
  520. X#define    termdef    1            /* don't define "term" external */
  521. X
  522. X#include        <stdio.h>
  523. X#include    "estruct.h"
  524. X#include        "edef.h"
  525. X
  526. X#if     IBMPC
  527. X
  528. X#define NROW    25                      /* Screen size.                 */
  529. X#define NCOL    80                      /* Edit if you want to.         */
  530. X#define    MARGIN    8            /* size of minimim margin and    */
  531. X#define    SCRSIZ    64            /* scroll size for extended lines */
  532. X#define    NPAUSE    200            /* # times thru update to pause */
  533. X#define BEL     0x07                    /* BEL character.               */
  534. X#define ESC     0x1B                    /* ESC character.               */
  535. X#define    SPACE    32            /* space character        */
  536. X#define    SCADD    0xb8000000L        /* address of screen RAM    */
  537. X
  538. Xint *scptr[NROW];            /* pointer to screen lines    */
  539. Xint sline[NCOL];            /* screen line image        */
  540. X
  541. Xextern  int     ttopen();               /* Forward references.          */
  542. Xextern  int     ttgetc();
  543. Xextern  int     ttputc();
  544. Xextern  int     ttflush();
  545. Xextern  int     ttclose();
  546. Xextern  int     ibmmove();
  547. Xextern  int     ibmeeol();
  548. Xextern  int     ibmeeop();
  549. Xextern  int     ibmbeep();
  550. Xextern  int     ibmopen();
  551. Xextern    int    ibmrev();
  552. Xextern    int    ibmclose();
  553. Xextern    int    ibmputc();
  554. X
  555. X#if    COLOR
  556. Xextern    int    ibmfcol();
  557. Xextern    int    ibmbcol();
  558. X
  559. Xint    cfcolor = -1;        /* current forground color */
  560. Xint    cbcolor = -1;        /* current background color */
  561. Xint    ctrans[] =        /* ansi to ibm color translation table */
  562. X    {0, 4, 2, 6, 1, 5, 3, 7};
  563. X#endif
  564. X
  565. X/*
  566. X * Standard terminal interface dispatch table. Most of the fields point into
  567. X * "termio" code.
  568. X */
  569. XTERM    term    = {
  570. X        NROW-1,
  571. X        NCOL,
  572. X    MARGIN,
  573. X    SCRSIZ,
  574. X    NPAUSE,
  575. X        ibmopen,
  576. X        ibmclose,
  577. X        ttgetc,
  578. X    ibmputc,
  579. X        ttflush,
  580. X        ibmmove,
  581. X        ibmeeol,
  582. X        ibmeeop,
  583. X        ibmbeep,
  584. X    ibmrev
  585. X#if    COLOR
  586. X    , ibmfcol,
  587. X    ibmbcol
  588. X#endif
  589. X};
  590. X
  591. Xextern union REGS rg;
  592. X
  593. X#if    COLOR
  594. Xibmfcol(color)        /* set the current output color */
  595. X
  596. Xint color;    /* color to set */
  597. X
  598. X{
  599. X    cfcolor = ctrans[color];
  600. X}
  601. X
  602. Xibmbcol(color)        /* set the current background color */
  603. X
  604. Xint color;    /* color to set */
  605. X
  606. X{
  607. X        cbcolor = ctrans[color];
  608. X}
  609. X#endif
  610. X
  611. Xibmmove(row, col)
  612. X{
  613. X    rg.h.ah = 2;        /* set cursor position function code */
  614. X    rg.h.dl = col;
  615. X    rg.h.dh = row;
  616. X    rg.h.bh = 0;        /* set screen page number */
  617. X    int86(0x10, &rg, &rg);
  618. X}
  619. X
  620. Xibmeeol()    /* erase to the end of the line */
  621. X
  622. X{
  623. X    int attr;    /* attribute byte mask to place in RAM */
  624. X    int *lnptr;    /* pointer to the destination line */
  625. X    int i;
  626. X    int ccol;    /* current column cursor lives */
  627. X    int crow;    /*       row    */
  628. X
  629. X    /* find the current cursor position */
  630. X    rg.h.ah = 3;        /* read cursor position function code */
  631. X    rg.h.bh = 0;        /* current video page */
  632. X    int86(0x10, &rg, &rg);
  633. X    ccol = rg.h.dl;        /* record current column */
  634. X    crow = rg.h.dh;        /* and row */
  635. X
  636. X    /* build the attribute byte and setup the screen pointer */
  637. X#if    COLOR
  638. X    attr = (((cbcolor & 15) << 4) | (cfcolor & 15)) << 8;
  639. X#else
  640. X    attr = 0x0700;
  641. X#endif
  642. X    lnptr = &sline[0];
  643. X    for (i=0; i < NCOL; i++)
  644. X        *lnptr++ = SPACE | attr;
  645. X
  646. X    /* wait for vertical retrace to be off */
  647. X    while ((inp(0x3da) & 8))
  648. X        ;
  649. X
  650. X    /* and to be back on */
  651. X    while ((inp(0x3da) & 8) == 0)
  652. X        ;
  653. X
  654. X    /* and send the string out */
  655. X    movmem(&sline[0], scptr[crow]+ccol, (NCOL-ccol)*2);
  656. X
  657. X}
  658. X
  659. Xibmputc(ch)    /* put a character at the current position in the
  660. X           current colors */
  661. X
  662. Xint ch;
  663. X
  664. X{
  665. X    rg.h.ah = 14;        /* write char to screen with current attrs */
  666. X    rg.h.al = ch;
  667. X#if    COLOR
  668. X    rg.h.bl = cfcolor;
  669. X#else
  670. X    rg.h.bl = 0x07;
  671. X#endif
  672. X    int86(0x10, &rg, &rg);
  673. X}
  674. X
  675. Xibmeeop()
  676. X{
  677. X    int attr;        /* attribute to fill screen with */
  678. X
  679. X    rg.h.ah = 6;        /* scroll page up function code */
  680. X    rg.h.al = 0;        /* # lines to scroll (clear it) */
  681. X    rg.x.cx = 0;        /* upper left corner of scroll */
  682. X    rg.x.dx = 0x174f;    /* lower right corner of scroll */
  683. X#if    COLOR
  684. X    attr = ((ctrans[gbcolor] & 15) << 4) | (ctrans[gfcolor] & 15);
  685. X#else
  686. X    attr = 0;
  687. X#endif
  688. X    rg.h.bh = attr;
  689. X    int86(0x10, &rg, &rg);
  690. X}
  691. X
  692. Xibmrev(state)        /* change reverse video state */
  693. X
  694. Xint state;    /* TRUE = reverse, FALSE = normal */
  695. X
  696. X{
  697. X    /* This never gets used under the IBM-PC driver */
  698. X}
  699. X
  700. Xibmbeep()
  701. X{
  702. X    bdos(6, BEL, 0);
  703. X}
  704. X
  705. Xibmopen()
  706. X{
  707. X    scinit();
  708. X    revexist = TRUE;
  709. X        ttopen();
  710. X}
  711. X
  712. Xibmclose()
  713. X
  714. X{
  715. X#if    COLOR
  716. X    ibmfcol(7);
  717. X    ibmbcol(0);
  718. X#endif
  719. X    ttclose();
  720. X}
  721. X
  722. Xscinit()    /* initialize the screen head pointers */
  723. X
  724. X{
  725. X    union {
  726. X        long laddr;    /* long form of address */
  727. X        int *paddr;    /* pointer form of address */
  728. X    } addr;
  729. X    int i;
  730. X
  731. X    /* initialize the screen pointer array */
  732. X    for (i = 0; i < NROW; i++) {
  733. X        addr.laddr = SCADD + (long)(NCOL * i * 2);
  734. X        scptr[i] = addr.paddr;
  735. X    }
  736. X}
  737. X
  738. Xscwrite(row, outstr, forg, bacg)    /* write a line out*/
  739. X
  740. Xint row;    /* row of screen to place outstr on */
  741. Xchar *outstr;    /* string to write out (must be NCOL long) */
  742. Xint forg;    /* forground color of string to write */
  743. Xint bacg;    /* background color */
  744. X
  745. X{
  746. X    int attr;    /* attribute byte mask to place in RAM */
  747. X    int *lnptr;    /* pointer to the destination line */
  748. X    int i;
  749. X
  750. X    /* build the attribute byte and setup the screen pointer */
  751. X#if    COLOR
  752. X    attr = (((ctrans[bacg] & 15) << 4) | (ctrans[forg] & 15)) << 8;
  753. X#else
  754. X    attr = (((bacg & 15) << 4) | (forg & 15)) << 8;
  755. X#endif
  756. X    lnptr = &sline[0];
  757. X    for (i=0; i<NCOL; i++)
  758. X        *lnptr++ = (outstr[i] & 255) | attr;
  759. X
  760. X    /* wait for vertical retrace to be off */
  761. X    while ((inp(0x3da) & 8))
  762. X        ;
  763. X
  764. X    /* and to be back on */
  765. X    while ((inp(0x3da) & 8) == 0)
  766. X        ;
  767. X
  768. X    /* and send the string out */
  769. X    movmem(&sline[0], scptr[row],NCOL*2);
  770. X}
  771. X#else
  772. Xibmhello()
  773. X{
  774. X}
  775. X#endif
  776. FRIDAY_NIGHT
  777. echo extracting - input.c
  778. sed 's/^X//' > input.c << 'FRIDAY_NIGHT'
  779. X/*    INPUT:    Various input routines for MicroEMACS 3.7
  780. X        written by Daniel Lawrence
  781. X        5/9/86                        */
  782. X
  783. X#include    <stdio.h>
  784. X#include    "estruct.h"
  785. X#include    "edef.h"
  786. X
  787. X/*
  788. X * Ask a yes or no question in the message line. Return either TRUE, FALSE, or
  789. X * ABORT. The ABORT status is returned if the user bumps out of the question
  790. X * with a ^G. Used any time a confirmation is required.
  791. X */
  792. X
  793. Xmlyesno(prompt)
  794. X
  795. Xchar *prompt;
  796. X
  797. X{
  798. X    char c;            /* input character */
  799. X    char buf[NPAT];        /* prompt to user */
  800. X
  801. X    for (;;) {
  802. X        /* build and prompt the user */
  803. X        strcpy(buf, prompt);
  804. X        strcat(buf, " [y/n]? ");
  805. X        mlwrite(buf);
  806. X
  807. X        /* get the responce */
  808. X        c = (*term.t_getchar)();
  809. X
  810. X        if (c == BELL)        /* Bail out! */
  811. X            return(ABORT);
  812. X
  813. X        if (c=='y' || c=='Y')
  814. X            return(TRUE);
  815. X
  816. X        if (c=='n' || c=='N')
  817. X            return(FALSE);
  818. X    }
  819. X}
  820. X
  821. X/*
  822. X * Write a prompt into the message line, then read back a response. Keep
  823. X * track of the physical position of the cursor. If we are in a keyboard
  824. X * macro throw the prompt away, and return the remembered response. This
  825. X * lets macros run at full speed. The reply is always terminated by a carriage
  826. X * return. Handle erase, kill, and abort keys.
  827. X */
  828. X
  829. Xmlreply(prompt, buf, nbuf)
  830. X    char *prompt;
  831. X    char *buf;
  832. X{
  833. X    return(mlreplyt(prompt,buf,nbuf,'\n'));
  834. X}
  835. X
  836. X/*    A more generalized prompt/reply function allowing the caller
  837. X    to specify the proper terminator. If the terminator is not
  838. X    a return ('\n') it will echo as "<NL>"
  839. X                            */
  840. Xmlreplyt(prompt, buf, nbuf, eolchar)
  841. X
  842. Xchar *prompt;
  843. Xchar *buf;
  844. Xchar eolchar;
  845. X
  846. X{
  847. X    register int cpos;    /* current character position in string */
  848. X    register int i;
  849. X    register int c;
  850. X    register int quotef;    /* are we quoting the next char? */
  851. X    register int status;    /* status return value */
  852. X
  853. X
  854. X    cpos = 0;
  855. X    quotef = FALSE;
  856. X
  857. X    if (kbdmop != NULL) {
  858. X        while ((c = *kbdmop++) != '\0')
  859. X            buf[cpos++] = c;
  860. X
  861. X        buf[cpos] = 0;
  862. X
  863. X        if (buf[0] == 0)
  864. X            return(FALSE);
  865. X
  866. X        return(TRUE);
  867. X    }
  868. X
  869. X    /* check to see if we are executing a command line */
  870. X    if (clexec) {
  871. X        status = nxtarg(buf);
  872. X        buf[nbuf-1] = 0;    /* make sure we null terminate it */
  873. X        return(status);
  874. X    }
  875. X
  876. X    mlwrite(prompt);
  877. X
  878. X    for (;;) {
  879. X    /* get a character from the user. if it is a <ret>, change it
  880. X       to a <NL>                            */
  881. X        c = (*term.t_getchar)();
  882. X        if (c == 0x0d)
  883. X            c = '\n';
  884. X
  885. X        if (c == eolchar && quotef == FALSE) {
  886. X            buf[cpos++] = 0;
  887. X
  888. X            if (kbdmip != NULL) {
  889. X                if (kbdmip+cpos > &kbdm[NKBDM-3]) {
  890. X                    ctrlg(FALSE, 0);
  891. X                    (*term.t_flush)();
  892. X                    return(ABORT);
  893. X                }
  894. X
  895. X                for (i=0; i<cpos; ++i)
  896. X                    *kbdmip++ = buf[i];
  897. X                }
  898. X
  899. X                (*term.t_move)(term.t_nrow, 0);
  900. X                ttcol = 0;
  901. X                (*term.t_flush)();
  902. X
  903. X                if (buf[0] == 0)
  904. X                    return(FALSE);
  905. X
  906. X                return(TRUE);
  907. X
  908. X            } else if (c == 0x07 && quotef == FALSE) {
  909. X                /* Bell, abort */
  910. X                (*term.t_putchar)('^');
  911. X                (*term.t_putchar)('G');
  912. X                ttcol += 2;
  913. X                ctrlg(FALSE, 0);
  914. X                (*term.t_flush)();
  915. X                return(ABORT);
  916. X
  917. X            } else if ((c==0x7F || c==0x08) && quotef==FALSE) {
  918. X                /* rubout/erase */
  919. X                if (cpos != 0) {
  920. X                    (*term.t_putchar)('\b');
  921. X                    (*term.t_putchar)(' ');
  922. X                    (*term.t_putchar)('\b');
  923. X                    --ttcol;
  924. X
  925. X                    if (buf[--cpos] < 0x20) {
  926. X                        (*term.t_putchar)('\b');
  927. X                        (*term.t_putchar)(' ');
  928. X                        (*term.t_putchar)('\b');
  929. X                        --ttcol;
  930. X                    }
  931. X
  932. X                    if (buf[cpos] == '\n') {
  933. X                        (*term.t_putchar)('\b');
  934. X                        (*term.t_putchar)('\b');
  935. X                        (*term.t_putchar)(' ');
  936. X                        (*term.t_putchar)(' ');
  937. X                        (*term.t_putchar)('\b');
  938. X                        (*term.t_putchar)('\b');
  939. X                        --ttcol;
  940. X                        --ttcol;
  941. X                    }
  942. X
  943. X                    (*term.t_flush)();
  944. X                }
  945. X
  946. X            } else if (c == 0x15 && quotef == FALSE) {
  947. X                /* C-U, kill */
  948. X                while (cpos != 0) {
  949. X                    (*term.t_putchar)('\b');
  950. X                    (*term.t_putchar)(' ');
  951. X                    (*term.t_putchar)('\b');
  952. X                    --ttcol;
  953. X
  954. X                    if (buf[--cpos] < 0x20) {
  955. X                        (*term.t_putchar)('\b');
  956. X                        (*term.t_putchar)(' ');
  957. X                        (*term.t_putchar)('\b');
  958. X                        --ttcol;
  959. X                    }
  960. X                }
  961. X
  962. X                (*term.t_flush)();
  963. X
  964. X            } else if (c == quotec && quotef == FALSE) {
  965. X                quotef = TRUE;
  966. X            } else {
  967. X                quotef = FALSE;
  968. X                if (cpos < nbuf-1) {
  969. X                    buf[cpos++] = c;
  970. X
  971. X                    if ((c < ' ') && (c != '\n')) {
  972. X                        (*term.t_putchar)('^');
  973. X                        ++ttcol;
  974. X                        c ^= 0x40;
  975. X                    }
  976. X
  977. X                    if (c != '\n')
  978. X                        (*term.t_putchar)(c);
  979. X                    else {    /* put out <NL> for <ret> */
  980. X                        (*term.t_putchar)('<');
  981. X                        (*term.t_putchar)('N');
  982. X                        (*term.t_putchar)('L');
  983. X                        (*term.t_putchar)('>');
  984. X                        ttcol += 3;
  985. X                    }
  986. X                ++ttcol;
  987. X                (*term.t_flush)();
  988. X            }
  989. X        }
  990. X    }
  991. X}
  992. X
  993. X/* get a command name from the command line. Command completion means
  994. X   that pressing a <SPACE> will attempt to complete an unfinished command
  995. X   name if it is unique.
  996. X*/
  997. X
  998. Xint (*getname())()
  999. X
  1000. X{
  1001. X    register int cpos;    /* current column on screen output */
  1002. X    register int c;
  1003. X    register char *sp;    /* pointer to string for output */
  1004. X    register NBIND *ffp;    /* first ptr to entry in name binding table */
  1005. X    register NBIND *cffp;    /* current ptr to entry in name binding table */
  1006. X    register NBIND *lffp;    /* last ptr to entry in name binding table */
  1007. X    char buf[NSTRING];    /* buffer to hold tentative command name */
  1008. X    int (*fncmatch())();
  1009. X
  1010. X    /* starting at the begining of the string buffer */
  1011. X    cpos = 0;
  1012. X
  1013. X    /* if we are executing a keyboard macro, fill our buffer from there,
  1014. X       and attempt a straight match */
  1015. X    if (kbdmop != NULL) {
  1016. X        while ((c = *kbdmop++) != '\0')
  1017. X            buf[cpos++] = c;
  1018. X
  1019. X        buf[cpos] = 0;
  1020. X
  1021. X        /* return the result of a match */
  1022. X        return(fncmatch(&buf[0]));
  1023. X    }
  1024. X
  1025. X    /* if we are executing a command line get the next arg and match it */
  1026. X    if (clexec) {
  1027. X        if (nxtarg(buf) != TRUE)
  1028. X            return(FALSE);
  1029. X        return(fncmatch(&buf[0]));
  1030. X    }
  1031. X
  1032. X    /* build a name string from the keyboard */
  1033. X    while (TRUE) {
  1034. X        c = (*term.t_getchar)();
  1035. X
  1036. X        /* if we are at the end, just match it */
  1037. X        if (c == 0x0d) {
  1038. X            buf[cpos] = 0;
  1039. X
  1040. X            /* save keyboard macro string if needed */
  1041. X            if (kbdtext(&buf[0]) == ABORT)
  1042. X                return( (int (*)()) NULL);
  1043. X
  1044. X            /* and match it off */
  1045. X            return(fncmatch(&buf[0]));
  1046. X
  1047. X        } else if (c == 0x07) {    /* Bell, abort */
  1048. X            (*term.t_putchar)('^');
  1049. X            (*term.t_putchar)('G');
  1050. X            ttcol += 2;
  1051. X            ctrlg(FALSE, 0);
  1052. X            (*term.t_flush)();
  1053. X            return( (int (*)()) NULL);
  1054. X
  1055. X        } else if (c == 0x7F || c == 0x08) {    /* rubout/erase */
  1056. X            if (cpos != 0) {
  1057. X                (*term.t_putchar)('\b');
  1058. X                (*term.t_putchar)(' ');
  1059. X                (*term.t_putchar)('\b');
  1060. X                --ttcol;
  1061. X                --cpos;
  1062. X                (*term.t_flush)();
  1063. X            }
  1064. X
  1065. X        } else if (c == 0x15) {    /* C-U, kill */
  1066. X            while (cpos != 0) {
  1067. X                (*term.t_putchar)('\b');
  1068. X                (*term.t_putchar)(' ');
  1069. X                (*term.t_putchar)('\b');
  1070. X                --cpos;
  1071. X                --ttcol;
  1072. X            }
  1073. X
  1074. X            (*term.t_flush)();
  1075. X
  1076. X        } else if (c == ' ') {
  1077. X/* <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */
  1078. X    /* attempt a completion */
  1079. X    buf[cpos] = 0;        /* terminate it for us */
  1080. X    ffp = &names[0];    /* scan for matches */
  1081. X    while (ffp->n_func != NULL) {
  1082. X        if (strncmp(buf, ffp->n_name, strlen(buf)) == 0) {
  1083. X            /* a possible match! More than one? */
  1084. X            if ((ffp + 1)->n_func == NULL ||
  1085. X               (strncmp(buf, (ffp+1)->n_name, strlen(buf)) != 0)) {
  1086. X                /* no...we match, print it */
  1087. X                sp = ffp->n_name + cpos;
  1088. X                while (*sp)
  1089. X                    (*term.t_putchar)(*sp++);
  1090. X                (*term.t_flush)();
  1091. X                return(ffp->n_func);
  1092. X            } else {
  1093. X/* << << << << << << << << << << << << << << << << << */
  1094. X    /* try for a partial match against the list */
  1095. X
  1096. X    /* first scan down until we no longer match the current input */
  1097. X    lffp = (ffp + 1);
  1098. X    while ((lffp+1)->n_func != NULL) {
  1099. X        if (strncmp(buf, (lffp+1)->n_name, strlen(buf)) != 0)
  1100. X            break;
  1101. X        ++lffp;
  1102. X    }
  1103. X
  1104. X    /* and now, attempt to partial complete the string, char at a time */
  1105. X    while (TRUE) {
  1106. X        /* add the next char in */
  1107. X        buf[cpos] = ffp->n_name[cpos];
  1108. X
  1109. X        /* scan through the candidates */
  1110. X        cffp = ffp + 1;
  1111. X        while (cffp <= lffp) {
  1112. X            if (cffp->n_name[cpos] != buf[cpos])
  1113. X                goto onward;
  1114. X            ++cffp;
  1115. X        }
  1116. X
  1117. X        /* add the character */
  1118. X        (*term.t_putchar)(buf[cpos++]);
  1119. X    }
  1120. X/* << << << << << << << << << << << << << << << << << */
  1121. X            }
  1122. X        }
  1123. X        ++ffp;
  1124. X    }
  1125. X
  1126. X    /* no match.....beep and onward */
  1127. X    (*term.t_beep)();
  1128. Xonward:;
  1129. X    (*term.t_flush)();
  1130. X/* <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */
  1131. X        } else {
  1132. X            if (cpos < NSTRING-1 && c > ' ') {
  1133. X                buf[cpos++] = c;
  1134. X                (*term.t_putchar)(c);
  1135. X            }
  1136. X
  1137. X            ++ttcol;
  1138. X            (*term.t_flush)();
  1139. X        }
  1140. X    }
  1141. X}
  1142. X
  1143. Xkbdtext(buf)    /* add this text string to the current keyboard macro
  1144. X           definition                        */
  1145. X
  1146. Xchar *buf;    /* text to add to keyboard macro */
  1147. X
  1148. X{
  1149. X    /* if we are defining a keyboard macro, save it */
  1150. X    if (kbdmip != NULL) {
  1151. X        if (kbdmip+strlen(buf) > &kbdm[NKBDM-4]) {
  1152. X            ctrlg(FALSE, 0);
  1153. X            (*term.t_flush)();
  1154. X            return(ABORT);
  1155. X        }
  1156. X
  1157. X        /* copy string in and null terminate it */
  1158. X        while (*buf)
  1159. X            *kbdmip++ = *buf++;
  1160. X        *kbdmip++ = 0;
  1161. X    }
  1162. X    return(TRUE);
  1163. X}
  1164. X
  1165. X/*    GET1KEY:    Get one keystroke. The only prefixs legal here
  1166. X            are the SPEC and CTRL prefixes.
  1167. X                                */
  1168. X
  1169. Xget1key()
  1170. X
  1171. X{
  1172. X    int    c;
  1173. X#if    AMIGA
  1174. X    int    d;
  1175. X#endif
  1176. X
  1177. X    /* get a keystroke */
  1178. X        c = (*term.t_getchar)();
  1179. X
  1180. X#if RAINBOW
  1181. X
  1182. X        if (c & Function_Key)
  1183. X                {
  1184. X                int i;
  1185. X
  1186. X                for (i = 0; i < lk_map_size; i++)
  1187. X                        if (c == lk_map[i][0])
  1188. X                                return lk_map[i][1];
  1189. X                }
  1190. X        else if (c == Shift + 015) return CTRL | 'J';
  1191. X        else if (c == Shift + 0x7F) return META | 0x7F;
  1192. X#endif
  1193. X
  1194. X#if    MSDOS
  1195. X    if (c == 0) {                /* Apply SPEC prefix    */
  1196. X            c = (*term.t_getchar)();
  1197. X            if (c>=0x00 && c<=0x1F)        /* control key? */
  1198. X                    c = CTRL | (c+'@');
  1199. X        return(SPEC | c);
  1200. X    }
  1201. X#endif
  1202. X
  1203. X#if    AMIGA
  1204. X    /* apply SPEC prefix */
  1205. X    if ((unsigned)c == 155) {
  1206. X        c = (*term.t_getchar)();
  1207. X
  1208. X        /* first try to see if it is a cursor key */
  1209. X        if ((c >= 'A' && c <= 'D') || c == 'S' || c == 'T')
  1210. X            return(SPEC | c);
  1211. X
  1212. X        /* next, a 2 char sequence */
  1213. X        d = (*term.t_getchar)();
  1214. X        if (d == '~')
  1215. X            return(SPEC | c);
  1216. X
  1217. X        /* decode a 3 char sequence */
  1218. X        c = d + 32;
  1219. X        /* if a shifted function key, eat the tilde */
  1220. X        if (d >= '0' && d <= '9')
  1221. X            d = (*term.t_getchar)();
  1222. X        return(SPEC | c);
  1223. X    }
  1224. X#endif
  1225. X
  1226. X#if  WANGPC
  1227. X    if (c == 0x1F) {            /* Apply SPEC prefix    */
  1228. X            c = (*term.t_getchar)();
  1229. X        return(SPEC | c);
  1230. X    }
  1231. X#endif
  1232. X
  1233. X        if (c>=0x00 && c<=0x1F)                 /* C0 control -> C-     */
  1234. X                c = CTRL | (c+'@');
  1235. X        return (c);
  1236. X}
  1237. X
  1238. X/*    GETCMD:    Get a command from the keyboard. Process all applicable
  1239. X        prefix keys
  1240. X                            */
  1241. Xgetcmd()
  1242. X
  1243. X{
  1244. X    int c;        /* fetched keystroke */
  1245. X
  1246. X    /* get initial character */
  1247. X    c = get1key();
  1248. X
  1249. X    /* process META prefix */
  1250. X    if (c == metac) {
  1251. X        c = get1key();
  1252. X            if (c>='a' && c<='z')        /* Force to upper */
  1253. X                    c -= 0x20;
  1254. X            if (c>=0x00 && c<=0x1F)        /* control key */
  1255. X                c = CTRL | (c+'@');
  1256. X        return(META | c);
  1257. X    }
  1258. X
  1259. X    /* process CTLX prefix */
  1260. X    if (c == ctlxc) {
  1261. X        c = get1key();
  1262. X            if (c>='a' && c<='z')        /* Force to upper */
  1263. X                    c -= 0x20;
  1264. X            if (c>=0x00 && c<=0x1F)        /* control key */
  1265. X                c = CTRL | (c+'@');
  1266. X        return(CTLX | c);
  1267. X    }
  1268. X
  1269. X    /* otherwise, just return it */
  1270. X    return(c);
  1271. X}
  1272. FRIDAY_NIGHT
  1273. echo extracting - isearch.c
  1274. sed 's/^X//' > isearch.c << 'FRIDAY_NIGHT'
  1275. X/*
  1276. X * The functions in this file implement commands that perform incremental
  1277. X * searches in the forward and backward directions.  This "ISearch" command
  1278. X * is intended to emulate the same command from the original EMACS 
  1279. X * implementation (ITS).  Contains references to routines internal to
  1280. X * SEARCH.C.
  1281. X *
  1282. X * REVISION HISTORY:
  1283. X *
  1284. X *    D. R. Banks 9-May-86
  1285. X *    - added ITS EMACSlike ISearch
  1286. X */
  1287. X
  1288. X#include        <stdio.h>
  1289. X#include    "estruct.h"
  1290. X#include        "edef.h"
  1291. X
  1292. X/*    string search input parameters    */
  1293. X
  1294. X#define    PTBEG    1    /* leave the point at the beginning on search */
  1295. X#define    PTEND    2    /* leave the point at the end on search */
  1296. X
  1297. X#define    CMDBUFLEN 256    /* Length of our command buffer */
  1298. X
  1299. Xextern int forscan();            /* Handy search routine */
  1300. Xextern int eq();            /* Compare chars, match case */
  1301. X
  1302. X/* A couple of "own" variables for re-eat */
  1303. X
  1304. Xint    (*saved_get_char)();        /* Get character routine */
  1305. Xint    eaten_char = -1;        /* Re-eaten char */
  1306. X
  1307. X/* A couple more "own" variables for the command string */
  1308. X
  1309. Xchar    cmd_buff[CMDBUFLEN];    /* Save the command args here */
  1310. Xint    cmd_offset;            /* Current offset into command buff */
  1311. Xint    cmd_reexecute = -1;        /* > 0 if re-executing command */
  1312. X
  1313. X/* Some character constants within ISearch */
  1314. X
  1315. X#define    IS_ABORT    0x07    /* Abort the isearch */
  1316. X#define IS_BACKSP    0x08    /* Delete previous char */
  1317. X#define    IS_TAB        0x09    /* Tab character (allowed search char) */
  1318. X#define IS_NEWLINE    0x0D    /* New line from keyboard (Carriage return) */
  1319. X#define    IS_QUOTE    0x11    /* Quote next character */
  1320. X#define IS_REVERSE    0x12    /* Search backward */
  1321. X#define    IS_FORWARD    0x13    /* Search forward */
  1322. X#define    IS_VMSQUOTE    0x16    /* VMS quote character */
  1323. X#define    IS_VMSFORW    0x18    /* Search forward for VMS */
  1324. X#define    IS_QUIT        0x1B    /* Exit the search */
  1325. X#define    IS_RUBOUT    0x7F    /* Delete previous character */
  1326. X
  1327. X/*
  1328. X * Subroutine to do incremental reverse search.  It actually uses the
  1329. X * same code as the normal incremental search, as both can go both ways.
  1330. X */
  1331. Xint risearch(f, n)
  1332. X{
  1333. X    LINE *curline;            /* Current line on entry          */
  1334. X    int  curoff;            /* Current offset on entry          */
  1335. X
  1336. X    /* remember the initial . on entry: */
  1337. X
  1338. X    curline = curwp->w_dotp;        /* Save the current line pointer      */
  1339. X    curoff  = curwp->w_doto;        /* Save the current offset          */
  1340. X
  1341. X    /* Make sure the search doesn't match where we already are:              */
  1342. X
  1343. X    backchar(TRUE, 1);            /* Back up a character              */
  1344. X
  1345. X    if (!(isearch(f, -n)))        /* Call ISearch backwards          */
  1346. X    {                    /* If error in search:              */
  1347. X    curwp->w_dotp = curline;    /* Reset the line pointer          */
  1348. X    curwp->w_doto = curoff;        /*  and the offset to original value  */
  1349. X    curwp->w_flag |= WFMOVE;    /* Say we've moved              */
  1350. X    update(FALSE);            /* And force an update              */
  1351. X    mlwrite ("[search failed]");    /* Say we died                  */
  1352. X    } else mlerase ();            /* If happy, just erase the cmd line  */
  1353. X}
  1354. X
  1355. X/* Again, but for the forward direction */
  1356. X
  1357. Xint fisearch(f, n)
  1358. X{
  1359. X    LINE *curline;            /* Current line on entry          */
  1360. X    int  curoff;            /* Current offset on entry          */
  1361. X
  1362. X    /* remember the initial . on entry: */
  1363. X
  1364. X    curline = curwp->w_dotp;        /* Save the current line pointer      */
  1365. X    curoff  = curwp->w_doto;        /* Save the current offset          */
  1366. X
  1367. X    /* do the search */
  1368. X
  1369. X    if (!(isearch(f, n)))        /* Call ISearch forwards          */
  1370. X    {                    /* If error in search:              */
  1371. X    curwp->w_dotp = curline;    /* Reset the line pointer          */
  1372. X    curwp->w_doto = curoff;        /*  and the offset to original value  */
  1373. X    curwp->w_flag |= WFMOVE;    /* Say we've moved              */
  1374. X    update(FALSE);            /* And force an update              */
  1375. X    mlwrite ("[search failed]");    /* Say we died                  */
  1376. X    } else mlerase ();            /* If happy, just erase the cmd line  */
  1377. X}
  1378. X
  1379. X/*
  1380. X * Subroutine to do an incremental search.  In general, this works similarly
  1381. X * to the older micro-emacs search function, except that the search happens
  1382. X * as each character is typed, with the screen and cursor updated with each
  1383. X * new search character.
  1384. X *
  1385. X * While searching forward, each successive character will leave the cursor
  1386. X * at the end of the entire matched string.  Typing a Control-S or Control-X
  1387. X * will cause the next occurrence of the string to be searched for (where the
  1388. X * next occurrence does NOT overlap the current occurrence).  A Control-R will
  1389. X * change to a backwards search, ESC will terminate the search and Control-G
  1390. X * will abort the search.  Rubout will back up to the previous match of the
  1391. X * string, or if the starting point is reached first, it will delete the
  1392. X * last character from the search string.
  1393. X *
  1394. X * While searching backward, each successive character will leave the cursor
  1395. X * at the beginning of the matched string.  Typing a Control-R will search
  1396. X * backward for the next occurrence of the string.  Control-S or Control-X
  1397. X * will revert the search to the forward direction.  In general, the reverse
  1398. X * incremental search is just like the forward incremental search inverted.
  1399. X *
  1400. X * In all cases, if the search fails, the user will be feeped, and the search
  1401. X * will stall until the pattern string is edited back into something that
  1402. X * exists (or until the search is aborted).
  1403. X */
  1404. Xisearch(f, n)
  1405. X{
  1406. X    int            status;        /* Search status */
  1407. X    int            col;        /* prompt column */
  1408. X    register int    cpos;        /* character number in search string  */
  1409. X    register int    c;        /* current input character */
  1410. X    char        pat_save[NPAT];    /* Saved copy of the old pattern str  */
  1411. X    LINE        *curline;    /* Current line on entry          */
  1412. X    int            curoff;        /* Current offset on entry          */
  1413. X    int            init_direction;    /* The initial search direction          */
  1414. X
  1415. X    /* Initialize starting conditions */
  1416. X
  1417. X    cmd_reexecute = -1;        /* We're not re-executing (yet?)      */
  1418. X    cmd_offset = 0;            /* Start at the beginning of the buff */
  1419. X    cmd_buff[0] = '\0';        /* Init the command buffer          */
  1420. X    strncpy (pat_save, pat, NPAT);    /* Save the old pattern string          */
  1421. X    curline = curwp->w_dotp;        /* Save the current line pointer      */
  1422. X    curoff  = curwp->w_doto;        /* Save the current offset          */
  1423. X    init_direction = n;            /* Save the initial search direction  */
  1424. X
  1425. X    /* This is a good place to start a re-execution: */
  1426. X
  1427. Xstart_over:
  1428. X
  1429. X    /* ask the user for the text of a pattern */
  1430. X    col = promptpattern("ISearch: ");        /* Prompt, remember the col   */
  1431. X
  1432. X    cpos = 0;                    /* Start afresh              */
  1433. X    status = TRUE;                /* Assume everything's cool   */
  1434. X
  1435. X    /*
  1436. X       Get the first character in the pattern.  If we get an initial Control-S
  1437. X       or Control-R, re-use the old search string and find the first occurrence
  1438. X     */
  1439. X
  1440. X    c = get_char();                /* Get the first character    */
  1441. X    if ((c == IS_FORWARD) ||
  1442. X        (c == IS_REVERSE) ||
  1443. X        (c == IS_VMSFORW))            /* Reuse old search string?   */
  1444. X    {
  1445. X        for (cpos = 0; pat[cpos] != 0; cpos++)    /* Yup, find the length          */
  1446. X            col = echochar(pat[cpos],col);    /*  and re-echo the string    */
  1447. X    if (c == IS_REVERSE) {            /* forward search?          */
  1448. X        n = -1;                /* No, search in reverse      */
  1449. X        backchar (TRUE, 1);            /* Be defensive about EOB     */
  1450. X    } else
  1451. X        n = 1;                /* Yes, search forward          */
  1452. X    status = scanmore(pat,n,status);    /* Do the search          */
  1453. X    c = get_char ();            /* Get another character      */
  1454. X    }
  1455. X
  1456. X    /* Top of the per character loop */
  1457. X            
  1458. X    for (;;)                    /* ISearch per character loop */
  1459. X    {
  1460. X    /* Check for magic characters first: */
  1461. X    /* Most cases here change the search */
  1462. X
  1463. X    switch (c)                /* dispatch on the input char */
  1464. X    {
  1465. X      case IS_ABORT:            /* If abort search request    */
  1466. X        return(FALSE);            /* Quit searching again          */
  1467. X
  1468. X      case IS_REVERSE:            /* If backward search          */
  1469. X      case IS_FORWARD:            /* If forward search          */
  1470. X      case IS_VMSFORW:            /*  of either flavor          */
  1471. X        if (c == IS_REVERSE)        /* If reverse search          */
  1472. X        n = -1;                /* Set the reverse direction  */
  1473. X        else                /* Otherwise,               */
  1474. X        n = 1;                /*  go forward              */
  1475. X        status = scanmore(pat,n,TRUE);    /* Start the search again     */
  1476. X        c = get_char ();            /* Get the next char          */
  1477. X        continue;                /* Go continue with the search*/
  1478. X
  1479. X      case IS_QUIT:                /* Want to quit searching?    */
  1480. X        return (TRUE);            /* Quit searching now          */
  1481. X
  1482. X      case IS_NEWLINE:            /* Carriage return          */
  1483. X        c = '\n';                /* Make it a new line          */
  1484. X        break;                /* Make sure we use it          */
  1485. X
  1486. X      case IS_QUOTE:            /* Quote character          */
  1487. X      case IS_VMSQUOTE:            /*  of either variety          */
  1488. X        c = get_char ();            /* Get the next char          */
  1489. X
  1490. X      case IS_TAB:                /* Generically allowed          */
  1491. X      case '\n':                /*  controlled characters     */
  1492. X        break;                /* Make sure we use it          */
  1493. X
  1494. X      case IS_BACKSP:            /* If a backspace:            */
  1495. X      case IS_RUBOUT:            /*  or if a Rubout:          */
  1496. X        if (cmd_offset <= 1)        /* Anything to delete?          */
  1497. X        return (TRUE);            /* No, just exit          */
  1498. X        --cmd_offset;            /* Back up over the Rubout    */
  1499. X        cmd_buff[--cmd_offset] = '\0'; /* Yes, delete last char   */
  1500. X        curwp->w_dotp = curline;        /* Reset the line pointer     */
  1501. X        curwp->w_doto = curoff;        /*  and the offset          */
  1502. X        n = init_direction;            /* Reset the search direction */
  1503. X        strncpy (pat, pat_save, NPAT);    /* Restore the old search str */
  1504. X        cmd_reexecute = 0;        /* Start the whole mess over  */
  1505. X        goto start_over;            /* Let it take care of itself */
  1506. X
  1507. X      /* Presumably a quasi-normal character comes here */
  1508. X
  1509. X      default:                /* All other chars              */
  1510. X        if (c < ' ')            /* Is it printable?          */
  1511. X        {                    /* Nope.              */
  1512. X        reeat (c);            /* Re-eat the char          */
  1513. X        return (TRUE);            /* And return the last status */
  1514. X        }
  1515. X    }  /* Switch */
  1516. X
  1517. X    /* I guess we got something to search for, so search for it          */
  1518. X
  1519. X    pat[cpos++] = c;            /* put the char in the buffer */
  1520. X    if (cpos >= NPAT)            /* too many chars in string?  */
  1521. X    {                    /* Yup.  Complain about it    */
  1522. X        mlwrite("? Search string too long");
  1523. X        return(TRUE);            /* Return an error          */
  1524. X    }
  1525. X    pat[cpos] = 0;                /* null terminate the buffer  */
  1526. X    col = echochar(c,col);            /* Echo the character          */
  1527. X    if (!status) {                /* If we lost last time          */
  1528. X        (*term.t_putchar)(BELL);        /* Feep again              */
  1529. X        (*term.t_flush)();            /* see that the feep feeps    */
  1530. X    } else                    /* Otherwise, we must have won*/
  1531. X        if (!(status = checknext(c,pat,n,status))) /* See if match          */
  1532. X        status = scanmore(pat,n,TRUE);    /*  or find the next match    */
  1533. X    c = get_char ();            /* Get the next char          */
  1534. X    } /* for {;;} */
  1535. X}
  1536. X
  1537. X/*
  1538. X * Trivial routine to insure that the next character in the search string is
  1539. X * still true to whatever we're pointing to in the buffer.  This routine will
  1540. X * not attempt to move the "point" if the match fails, although it will 
  1541. X * implicitly move the "point" if we're forward searching, and find a match,
  1542. X * since that's the way forward isearch works.
  1543. X *
  1544. X * If the compare fails, we return FALSE and assume the caller will call
  1545. X * scanmore or something.
  1546. X */
  1547. X
  1548. Xint checknext (chr, patrn, dir, sts)/* Check next character in search string */
  1549. Xchar    chr;            /* Next char to look for         */
  1550. Xchar    *patrn;            /* The entire search string (incl chr)   */
  1551. Xint    dir;            /* Search direction             */
  1552. Xint    sts;            /* Search status             */
  1553. X{
  1554. X    register LINE *curline;        /* current line during scan          */
  1555. X    register int curoff;        /* position within current line          */
  1556. X    register int buffchar;        /* character at current position      */
  1557. X    int status;                /* how well things go              */
  1558. X
  1559. X    if (!sts) return(FALSE);        /* Don't try unless ok so far          */
  1560. X
  1561. X    /* setup the local scan pointer to current "." */
  1562. X
  1563. X    curline = curwp->w_dotp;        /* Get the current line structure     */
  1564. X    curoff  = curwp->w_doto;        /* Get the offset within that line    */
  1565. X
  1566. X    if (dir > 0)            /* If searching forward              */
  1567. X    {
  1568. X        if (curoff == llength(curline)) /* If at end of line              */
  1569. X        {
  1570. X        curline = lforw(curline);    /* Skip to the next line          */
  1571. X        if (curline == curbp->b_linep)
  1572. X        return (FALSE);        /* Abort if at end of buffer          */
  1573. X        curoff = 0;            /* Start at the beginning of the line */
  1574. X        buffchar = '\n';        /* And say the next char is NL          */
  1575. X    } else
  1576. X        buffchar = lgetc(curline, curoff++); /* Get the next char          */
  1577. X    if (status = eq(buffchar, chr))    /* Is it what we're looking for?      */
  1578. X    {
  1579. X        curwp->w_dotp = curline;    /* Yes, set the buffer's point          */
  1580. X        curwp->w_doto = curoff;    /*  to the matched character          */
  1581. X        curwp->w_flag |= WFMOVE;    /* Say that we've moved              */
  1582. X    }
  1583. X    return (status);        /* And return the status          */
  1584. X    } else                /* Else, if reverse search:          */
  1585. X    return (match_pat (patrn));    /* See if we're in the right place    */
  1586. X}
  1587. X
  1588. X/*
  1589. X * This hack will search for the next occurrence of <pat> in the buffer, either
  1590. X * forward or backward.  It is called with the status of the prior search
  1591. X * attempt, so that it knows not to bother if it didn't work last time.  If
  1592. X * we can't find any more matches, "point" is left where it was before.  If
  1593. X * we do find a match, "point" will be at the end of the matched string for
  1594. X * forward searches and at the beginning of the matched string for reverse
  1595. X * searches.
  1596. X */
  1597. Xint scanmore(patrn,dir,sts)    /* search forward or back for a pattern          */
  1598. Xchar    *patrn;            /* string to scan for                  */
  1599. Xint    dir;            /* direction to search                  */
  1600. Xint    sts;            /* previous search status              */
  1601. X{
  1602. X    if (sts)             /* don't try unless successful last time      */
  1603. X    {
  1604. X        if (dir < 0)                /* reverse search?          */
  1605. X        sts = bakscan(patrn);        /* Yes, call our hacky routine*/
  1606. X    else
  1607. X        sts = forscan(patrn,PTEND);        /* Nope. Go forward          */
  1608. X    }
  1609. X    if (!sts) {
  1610. X        (*term.t_putchar)(BELL);        /* Feep if search fails       */
  1611. X    (*term.t_flush)();            /* see that the feep feeps    */
  1612. X    }
  1613. X    return(sts);                /* else, don't even try          */
  1614. X}
  1615. X
  1616. X/*
  1617. X * The following is a minimal implementation of the reverse of "forscan".
  1618. X * We aren't using the routine in SEARCH.C because it likes to type stuff,
  1619. X * but the real solution is probably to fix that instead of duplicate the
  1620. X * code here like we're doing.  On the other hand, we don't want to touch
  1621. X * more modules than we have to for this first round ...
  1622. X *
  1623. X * This always leaves "." at the beginning of the matched pattern string
  1624. X */
  1625. X
  1626. Xint bakscan (patrn)        /* Scan backwards for a match              */
  1627. Xchar    *patrn;            /* Search string to be matched              */
  1628. X{
  1629. X    LINE *initline;            /* initial line pointer before scan   */
  1630. X    int initoff;            /* position within initial line          */
  1631. X
  1632. X    /* Remember "point" on entry: */
  1633. X
  1634. X    initline = curwp->w_dotp;        /* Get the current line structure     */
  1635. X    initoff  = curwp->w_doto;        /* Get the offset within that line    */
  1636. X
  1637. X    /*
  1638. X     * Loop here, stepping the cursor until we match or until we reach the top
  1639. X     * of the buffer
  1640. X     */
  1641. X
  1642. X    while (backchar(TRUE, 1))            /* As long as there're chars  */
  1643. X    if (match_pat (patrn))            /* See if we match          */
  1644. X        return (TRUE);            /* Yep.  Stop'er right here   */
  1645. X    curwp->w_dotp = initline;            /* Top of buffer, just reset  */
  1646. X    curwp->w_doto = initoff;            /*   to original "point"      */
  1647. X    curwp->w_flag |= WFMOVE;            /* In case backchar moved us  */
  1648. X    return (FALSE);                /* And return failure          */
  1649. X}
  1650. X
  1651. X/*
  1652. X * The following is a worker subroutine used by the reverse search.  It
  1653. X * compares the pattern string with the characters at "." for equality. If
  1654. X * any characters mismatch, it will return FALSE.
  1655. X *
  1656. X * This isn't used for forward searches, because forward searches leave "."
  1657. X * at the end of the search string (instead of in front), so all that needs to
  1658. X * be done is match the last char input.
  1659. X */
  1660. X
  1661. Xint match_pat (patrn)    /* See if the pattern string matches string at "."   */
  1662. Xchar    *patrn;        /* String to match to buffer                 */
  1663. X{
  1664. X    register int  i;            /* Generic loop index/offset          */
  1665. X    register int buffchar;        /* character at current position      */
  1666. X    register LINE *curline;        /* current line during scan          */
  1667. X    register int curoff;        /* position within current line          */
  1668. X
  1669. X    /* setup the local scan pointer to current "." */
  1670. X
  1671. X    curline = curwp->w_dotp;        /* Get the current line structure     */
  1672. X    curoff  = curwp->w_doto;        /* Get the offset within that line    */
  1673. X
  1674. X    /* top of per character compare loop: */
  1675. X
  1676. X    for (i = 0; i < strlen(patrn); i++)    /* Loop for all characters in patrn   */
  1677. X    {
  1678. X        if (curoff == llength(curline)) /* If at end of line              */
  1679. X        {
  1680. X        curline = lforw(curline);    /* Skip to the next line          */
  1681. X        curoff = 0;            /* Start at the beginning of the line */
  1682. X        if (curline == curbp->b_linep)
  1683. X        return (FALSE);        /* Abort if at end of buffer          */
  1684. X        buffchar = '\n';        /* And say the next char is NL          */
  1685. X    } else
  1686. X        buffchar = lgetc(curline, curoff++); /* Get the next char          */
  1687. X    if (!eq(buffchar, patrn[i]))    /* Is it what we're looking for?      */
  1688. X        return (FALSE);        /* Nope, just punt it then          */
  1689. X    }
  1690. X    return (TRUE);            /* Everything matched? Let's celebrate*/
  1691. X}
  1692. X
  1693. X/* Routine to prompt for I-Search string. */
  1694. X
  1695. Xint promptpattern(prompt)
  1696. Xchar *prompt;
  1697. X{
  1698. X    char tpat[NPAT+20];
  1699. X
  1700. X    strcpy(tpat, prompt);        /* copy prompt to output string */
  1701. X    strcat(tpat, " [");            /* build new prompt string */
  1702. X    expandp(pat, &tpat[strlen(tpat)], NPAT/2);    /* add old pattern */
  1703. X    strcat(tpat, "]<ESC>: ");
  1704. X
  1705. X    /* check to see if we are executing a command line */
  1706. X    if (!clexec) {
  1707. X    mlwrite(tpat);
  1708. X    }
  1709. X    return(strlen(tpat));
  1710. X}
  1711. X
  1712. X/* routine to echo i-search characters */
  1713. X
  1714. Xint echochar(c,col)
  1715. Xint    c;    /* character to be echoed */
  1716. Xint    col;    /* column to be echoed in */
  1717. X{
  1718. X    movecursor(term.t_nrow,col);        /* Position the cursor          */
  1719. X    if ((c < ' ') || (c == 0x7F))        /* Control character?          */
  1720. X    {
  1721. X    switch (c)                /* Yes, dispatch special cases*/
  1722. X    {
  1723. X      case '\n':                /* Newline              */
  1724. X        (*term.t_putchar)('<');
  1725. X        (*term.t_putchar)('N');
  1726. X        (*term.t_putchar)('L');
  1727. X        (*term.t_putchar)('>');
  1728. X        col += 3;
  1729. X        break;
  1730. X
  1731. X      case '\t':                /* Tab                  */
  1732. X        (*term.t_putchar)('<');
  1733. X        (*term.t_putchar)('T');
  1734. X        (*term.t_putchar)('A');
  1735. X        (*term.t_putchar)('B');
  1736. X        (*term.t_putchar)('>');
  1737. X        col += 4;
  1738. X        break;
  1739. X
  1740. X      case 0x7F:                /* Rubout:              */
  1741. X        (*term.t_putchar)('^');        /* Output a funny looking     */
  1742. X        (*term.t_putchar)('?');        /*  indication of Rubout      */
  1743. X        col++;                /* Count the extra char       */
  1744. X        break;
  1745. X
  1746. X      default:                /* Vanilla control char       */
  1747. X        (*term.t_putchar)('^');        /* Yes, output prefix          */
  1748. X            (*term.t_putchar)(c+0x40);        /* Make it "^X"              */
  1749. X        col++;                /* Count this char          */
  1750. X    }
  1751. X    } else
  1752. X    (*term.t_putchar)(c);            /* Otherwise, output raw char */
  1753. X    (*term.t_flush)();                /* Flush the output          */
  1754. X    return(++col);                /* return the new column no   */
  1755. X}
  1756. X
  1757. X/*
  1758. X * Routine to get the next character from the input stream.  If we're reading
  1759. X * from the real terminal, force a screen update before we get the char. 
  1760. X * Otherwise, we must be re-executing the command string, so just return the
  1761. X * next character.
  1762. X */
  1763. X
  1764. Xint get_char ()
  1765. X{
  1766. X    int    c;                /* A place to get a character          */
  1767. X
  1768. X    /* See if we're re-executing: */
  1769. X
  1770. X    if (cmd_reexecute >= 0)        /* Is there an offset?              */
  1771. X    if ((c = cmd_buff[cmd_reexecute++]) != 0)
  1772. X        return (c);            /* Yes, return any character          */
  1773. X
  1774. X    /* We're not re-executing (or aren't any more).  Try for a real char      */
  1775. X
  1776. X    cmd_reexecute = -1;        /* Say we're in real mode again          */
  1777. X    update(FALSE);            /* Pretty up the screen              */
  1778. X    if (cmd_offset >= CMDBUFLEN-1)    /* If we're getting too big ...          */
  1779. X    {
  1780. X    mlwrite ("? command too long");    /* Complain loudly and bitterly          */
  1781. X    return (IS_QUIT);        /* And force a quit              */
  1782. X    }
  1783. X    c = (*term.t_getchar)();        /* Get the next character          */
  1784. X    cmd_buff[cmd_offset++] = c; /* Save the char for next time        */
  1785. X    cmd_buff[cmd_offset] = '\0';/* And terminate the buffer          */
  1786. X    return (c);                /* Return the character              */
  1787. X}
  1788. X
  1789. X/*
  1790. X * Hacky routine to re-eat a character.  This will save the character to be
  1791. X * re-eaten by redirecting the input call to a routine here.  Hack, etc.
  1792. X */
  1793. X
  1794. X/* Come here on the next term.t_getchar call: */
  1795. X
  1796. Xint uneat()
  1797. X{
  1798. X    int c;
  1799. X
  1800. X    term.t_getchar = saved_get_char;    /* restore the routine address          */
  1801. X    c = eaten_char;            /* Get the re-eaten char          */
  1802. X    eaten_char = -1;            /* Clear the old char              */
  1803. X    return(c);                /* and return the last char          */
  1804. X}
  1805. X
  1806. Xint reeat(c)
  1807. Xint    c;
  1808. X{
  1809. X    if (eaten_char != -1)        /* If we've already been here          */
  1810. X    return (NULL);            /* Don't do it again              */
  1811. X    eaten_char = c;            /* Else, save the char for later      */
  1812. X    saved_get_char = term.t_getchar;    /* Save the char get routine          */
  1813. X    term.t_getchar = uneat;        /* Replace it with ours              */
  1814. X}
  1815. X
  1816. FRIDAY_NIGHT
  1817. echo es.6 completed!
  1818. : That's all folks!
  1819.  
  1820.