home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume1 / 8711 / 10 < prev    next >
Text File  |  1987-11-17  |  35KB  |  1,447 lines

  1. Article 77 of comp.sources.misc:
  2. Path: tut!osu-cis!cbosgd!mandrill!hal!ncoast!allbery
  3. From: nwd@j.cc.purdue.edu (Daniel Lawrence)
  4. Newsgroups: comp.sources.misc
  5. Subject: MicroEmacs 3.9 (Part 1 of 16)
  6. Message-ID: <5648@ncoast.UUCP>
  7. Date: 14 Nov 87 21:05:32 GMT
  8. Sender: allbery@ncoast.UUCP
  9. Lines: 1432
  10. Approved: allbery@ncoast.UUCP
  11. X-Archive: comp.sources.misc/8711/10
  12.  
  13. # This is a shar archive.
  14. # Remove everything above this line.
  15. # Run the file through sh, not csh.
  16. # (type `sh mes.1')
  17. # If you do not see the message
  18. #    `mes.1 completed!'
  19. # then the file was incomplete.
  20. echo extracting - ansi.c
  21. sed 's/^X//' > ansi.c << 'FRIDAY_NIGHT'
  22. X/*
  23. X * The routines in this file provide support for ANSI style terminals
  24. X * over a serial line. The serial I/O services are provided by routines in
  25. X * "termio.c". It compiles into nothing if not an ANSI device.
  26. X */
  27. X
  28. X#define    termdef    1            /* don't define "term" external */
  29. X
  30. X#include        <stdio.h>
  31. X#include    "estruct.h"
  32. X#include        "edef.h"
  33. X
  34. X#if     ANSI
  35. X
  36. X#if    AMIGA
  37. X#define NROW    23                      /* Screen size.                 */
  38. X#define NCOL    77                      /* Edit if you want to.         */
  39. X#else
  40. X#define NROW    25                      /* Screen size.                 */
  41. X#define NCOL    80                      /* Edit if you want to.         */
  42. X#endif
  43. X#define    NPAUSE    100            /* # times thru update to pause */
  44. X#define    MARGIN    8            /* size of minimim margin and    */
  45. X#define    SCRSIZ    64            /* scroll size for extended lines */
  46. X#define BEL     0x07                    /* BEL character.               */
  47. X#define ESC     0x1B                    /* ESC character.               */
  48. X
  49. Xextern  int     ttopen();               /* Forward references.          */
  50. Xextern  int     ttgetc();
  51. Xextern  int     ttputc();
  52. Xextern  int     ttflush();
  53. Xextern  int     ttclose();
  54. Xextern  int     ansimove();
  55. Xextern  int     ansieeol();
  56. Xextern  int     ansieeop();
  57. Xextern  int     ansibeep();
  58. Xextern  int     ansiopen();
  59. Xextern    int    ansirev();
  60. Xextern    int    ansiclose();
  61. Xextern    int    ansikopen();
  62. Xextern    int    ansikclose();
  63. Xextern    int    ansicres();
  64. X
  65. X#if    COLOR
  66. Xextern    int    ansifcol();
  67. Xextern    int    ansibcol();
  68. X
  69. Xint    cfcolor = -1;        /* current forground color */
  70. Xint    cbcolor = -1;        /* current background color */
  71. X
  72. X#if    AMIGA
  73. X/* apperently the AMIGA does not follow the ANSI standards as
  74. X   regards to colors....maybe because of the default pallette
  75. X   settings?
  76. X*/
  77. X
  78. Xint coltran[8] = {2, 3, 5, 7, 0, 4, 6, 1};    /* color translation table */
  79. X#endif
  80. X#endif
  81. X
  82. X/*
  83. X * Standard terminal interface dispatch table. Most of the fields point into
  84. X * "termio" code.
  85. X */
  86. XTERM    term    = {
  87. X    NROW-1,
  88. X        NROW-1,
  89. X        NCOL,
  90. X        NCOL,
  91. X    MARGIN,
  92. X    SCRSIZ,
  93. X    NPAUSE,
  94. X        ansiopen,
  95. X        ansiclose,
  96. X    ansikopen,
  97. X    ansikclose,
  98. X        ttgetc,
  99. X        ttputc,
  100. X        ttflush,
  101. X        ansimove,
  102. X        ansieeol,
  103. X        ansieeop,
  104. X        ansibeep,
  105. X    ansirev,
  106. X    ansicres
  107. X#if    COLOR
  108. X    , ansifcol,
  109. X    ansibcol
  110. X#endif
  111. X};
  112. X
  113. X#if    COLOR
  114. Xansifcol(color)        /* set the current output color */
  115. X
  116. Xint color;    /* color to set */
  117. X
  118. X{
  119. X    if (color == cfcolor)
  120. X        return;
  121. X    ttputc(ESC);
  122. X    ttputc('[');
  123. X#if    AMIGA
  124. X    ansiparm(coltran[color]+30);
  125. X#else
  126. X    ansiparm(color+30);
  127. X#endif
  128. X    ttputc('m');
  129. X    cfcolor = color;
  130. X}
  131. X
  132. Xansibcol(color)        /* set the current background color */
  133. X
  134. Xint color;    /* color to set */
  135. X
  136. X{
  137. X    if (color == cbcolor)
  138. X        return;
  139. X    ttputc(ESC);
  140. X    ttputc('[');
  141. X#if    AMIGA
  142. X    ansiparm(coltran[color]+40);
  143. X#else
  144. X    ansiparm(color+40);
  145. X#endif
  146. X    ttputc('m');
  147. X        cbcolor = color;
  148. X}
  149. X#endif
  150. X
  151. Xansimove(row, col)
  152. X{
  153. X        ttputc(ESC);
  154. X        ttputc('[');
  155. X        ansiparm(row+1);
  156. X        ttputc(';');
  157. X        ansiparm(col+1);
  158. X        ttputc('H');
  159. X}
  160. X
  161. Xansieeol()
  162. X{
  163. X        ttputc(ESC);
  164. X        ttputc('[');
  165. X        ttputc('K');
  166. X}
  167. X
  168. Xansieeop()
  169. X{
  170. X#if    COLOR
  171. X    ansifcol(gfcolor);
  172. X    ansibcol(gbcolor);
  173. X#endif
  174. X        ttputc(ESC);
  175. X        ttputc('[');
  176. X        ttputc('J');
  177. X}
  178. X
  179. Xansirev(state)        /* change reverse video state */
  180. X
  181. Xint state;    /* TRUE = reverse, FALSE = normal */
  182. X
  183. X{
  184. X#if    COLOR
  185. X    int ftmp, btmp;        /* temporaries for colors */
  186. X#endif
  187. X
  188. X    ttputc(ESC);
  189. X    ttputc('[');
  190. X    ttputc(state ? '7': '0');
  191. X    ttputc('m');
  192. X#if    COLOR
  193. X    if (state == FALSE) {
  194. X        ftmp = cfcolor;
  195. X        btmp = cbcolor;
  196. X        cfcolor = -1;
  197. X        cbcolor = -1;
  198. X        ansifcol(ftmp);
  199. X        ansibcol(btmp);
  200. X    }
  201. X#endif
  202. X}
  203. X
  204. Xansicres()    /* change screen resolution */
  205. X
  206. X{
  207. X    return(TRUE);
  208. X}
  209. X
  210. Xspal(dummy)        /* change pallette settings */
  211. X
  212. X{
  213. X    /* none for now */
  214. X}
  215. X
  216. Xansibeep()
  217. X{
  218. X        ttputc(BEL);
  219. X        ttflush();
  220. X}
  221. X
  222. Xansiparm(n)
  223. Xregister int    n;
  224. X{
  225. X        register int q,r;
  226. X
  227. X        q = n/10;
  228. X        if (q != 0) {
  229. X        r = q/10;
  230. X        if (r != 0) {
  231. X            ttputc((r%10)+'0');
  232. X        }
  233. X        ttputc((q%10) + '0');
  234. X        }
  235. X        ttputc((n%10) + '0');
  236. X}
  237. X
  238. Xansiopen()
  239. X{
  240. X#if     V7 | USG | BSD
  241. X        register char *cp;
  242. X        char *getenv();
  243. X
  244. X        if ((cp = getenv("TERM")) == NULL) {
  245. X                puts("Shell variable TERM not defined!");
  246. X                exit(1);
  247. X        }
  248. X        if (strcmp(cp, "vt100") != 0) {
  249. X                puts("Terminal type not 'vt100'!");
  250. X                exit(1);
  251. X        }
  252. X#endif
  253. X    strcpy(sres, "NORMAL");
  254. X    revexist = TRUE;
  255. X        ttopen();
  256. X}
  257. X
  258. Xansiclose()
  259. X
  260. X{
  261. X#if    COLOR
  262. X    ansifcol(7);
  263. X    ansibcol(0);
  264. X#endif
  265. X    ttclose();
  266. X}
  267. X
  268. Xansikopen()    /* open the keyboard (a noop here) */
  269. X
  270. X{
  271. X}
  272. X
  273. Xansikclose()    /* close the keyboard (a noop here) */
  274. X
  275. X{
  276. X}
  277. X
  278. X#if    FLABEL
  279. Xfnclabel(f, n)        /* label a function key */
  280. X
  281. Xint f,n;    /* default flag, numeric argument [unused] */
  282. X
  283. X{
  284. X    /* on machines with no function keys...don't bother */
  285. X    return(TRUE);
  286. X}
  287. X#endif
  288. X#else
  289. Xansihello()
  290. X{
  291. X}
  292. X#endif
  293. FRIDAY_NIGHT
  294. echo extracting - basic.c
  295. sed 's/^X//' > basic.c << 'FRIDAY_NIGHT'
  296. X/*
  297. X * The routines in this file move the cursor around on the screen. They
  298. X * compute a new value for the cursor, then adjust ".". The display code
  299. X * always updates the cursor location, so only moves between lines, or
  300. X * functions that adjust the top line in the window and invalidate the
  301. X * framing, are hard.
  302. X */
  303. X#include        <stdio.h>
  304. X#include    "estruct.h"
  305. X#include        "edef.h"
  306. X
  307. X/*
  308. X * Move the cursor to the
  309. X * beginning of the current line.
  310. X * Trivial.
  311. X */
  312. Xgotobol(f, n)
  313. X{
  314. X        curwp->w_doto  = 0;
  315. X        return (TRUE);
  316. X}
  317. X
  318. X/*
  319. X * Move the cursor backwards by "n" characters. If "n" is less than zero call
  320. X * "forwchar" to actually do the move. Otherwise compute the new cursor
  321. X * location. Error if you try and move out of the buffer. Set the flag if the
  322. X * line pointer for dot changes.
  323. X */
  324. Xbackchar(f, n)
  325. Xregister int    n;
  326. X{
  327. X        register LINE   *lp;
  328. X
  329. X        if (n < 0)
  330. X                return (forwchar(f, -n));
  331. X        while (n--) {
  332. X                if (curwp->w_doto == 0) {
  333. X                        if ((lp=lback(curwp->w_dotp)) == curbp->b_linep)
  334. X                                return (FALSE);
  335. X                        curwp->w_dotp  = lp;
  336. X                        curwp->w_doto  = llength(lp);
  337. X                        curwp->w_flag |= WFMOVE;
  338. X                } else
  339. X                        curwp->w_doto--;
  340. X        }
  341. X        return (TRUE);
  342. X}
  343. X
  344. X/*
  345. X * Move the cursor to the end of the current line. Trivial. No errors.
  346. X */
  347. Xgotoeol(f, n)
  348. X{
  349. X        curwp->w_doto  = llength(curwp->w_dotp);
  350. X        return (TRUE);
  351. X}
  352. X
  353. X/*
  354. X * Move the cursor forwards by "n" characters. If "n" is less than zero call
  355. X * "backchar" to actually do the move. Otherwise compute the new cursor
  356. X * location, and move ".". Error if you try and move off the end of the
  357. X * buffer. Set the flag if the line pointer for dot changes.
  358. X */
  359. Xforwchar(f, n)
  360. Xregister int    n;
  361. X{
  362. X        if (n < 0)
  363. X                return (backchar(f, -n));
  364. X        while (n--) {
  365. X                if (curwp->w_doto == llength(curwp->w_dotp)) {
  366. X                        if (curwp->w_dotp == curbp->b_linep)
  367. X                                return (FALSE);
  368. X                        curwp->w_dotp  = lforw(curwp->w_dotp);
  369. X                        curwp->w_doto  = 0;
  370. X                        curwp->w_flag |= WFMOVE;
  371. X                } else
  372. X                        curwp->w_doto++;
  373. X        }
  374. X        return (TRUE);
  375. X}
  376. X
  377. Xgotoline(f, n)        /* move to a particular line.
  378. X               argument (n) must be a positive integer for
  379. X               this to actually do anything        */
  380. X
  381. X{
  382. X    register int status;    /* status return */
  383. X    char arg[NSTRING];    /* buffer to hold argument */
  384. X
  385. X    /* get an argument if one doesnt exist */
  386. X    if (f == FALSE) {
  387. X        if ((status = mlreply("Line to GOTO: ", arg, NSTRING)) != TRUE) {
  388. X            mlwrite("[Aborted]");
  389. X            return(status);
  390. X        }
  391. X        n = atoi(arg);
  392. X    }
  393. X
  394. X    if (n < 1)        /* if a bogus argument...then leave */
  395. X        return(FALSE);
  396. X
  397. X    /* first, we go to the start of the buffer */
  398. X        curwp->w_dotp  = lforw(curbp->b_linep);
  399. X        curwp->w_doto  = 0;
  400. X    return(forwline(f, n-1));
  401. X}
  402. X
  403. X/*
  404. X * Goto the beginning of the buffer. Massive adjustment of dot. This is
  405. X * considered to be hard motion; it really isn't if the original value of dot
  406. X * is the same as the new value of dot. Normally bound to "M-<".
  407. X */
  408. Xgotobob(f, n)
  409. X{
  410. X        curwp->w_dotp  = lforw(curbp->b_linep);
  411. X        curwp->w_doto  = 0;
  412. X        curwp->w_flag |= WFHARD;
  413. X        return (TRUE);
  414. X}
  415. X
  416. X/*
  417. X * Move to the end of the buffer. Dot is always put at the end of the file
  418. X * (ZJ). The standard screen code does most of the hard parts of update.
  419. X * Bound to "M->".
  420. X */
  421. Xgotoeob(f, n)
  422. X{
  423. X        curwp->w_dotp  = curbp->b_linep;
  424. X        curwp->w_doto  = 0;
  425. X        curwp->w_flag |= WFHARD;
  426. X        return (TRUE);
  427. X}
  428. X
  429. X/*
  430. X * Move forward by full lines. If the number of lines to move is less than
  431. X * zero, call the backward line function to actually do it. The last command
  432. X * controls how the goal column is set. Bound to "C-N". No errors are
  433. X * possible.
  434. X */
  435. Xforwline(f, n)
  436. X{
  437. X        register LINE   *dlp;
  438. X
  439. X        if (n < 0)
  440. X                return (backline(f, -n));
  441. X
  442. X    /* if we are on the last line as we start....fail the command */
  443. X    if (curwp->w_dotp == curbp->b_linep)
  444. X        return(FALSE);
  445. X
  446. X    /* if the last command was not note a line move,
  447. X       reset the goal column */
  448. X        if ((lastflag&CFCPCN) == 0)
  449. X                curgoal = getccol(FALSE);
  450. X
  451. X    /* flag this command as a line move */
  452. X        thisflag |= CFCPCN;
  453. X
  454. X    /* and move the point down */
  455. X        dlp = curwp->w_dotp;
  456. X        while (n-- && dlp!=curbp->b_linep)
  457. X                dlp = lforw(dlp);
  458. X
  459. X    /* reseting the current position */
  460. X        curwp->w_dotp  = dlp;
  461. X        curwp->w_doto  = getgoal(dlp);
  462. X        curwp->w_flag |= WFMOVE;
  463. X        return (TRUE);
  464. X}
  465. X
  466. X/*
  467. X * This function is like "forwline", but goes backwards. The scheme is exactly
  468. X * the same. Check for arguments that are less than zero and call your
  469. X * alternate. Figure out the new line and call "movedot" to perform the
  470. X * motion. No errors are possible. Bound to "C-P".
  471. X */
  472. Xbackline(f, n)
  473. X{
  474. X        register LINE   *dlp;
  475. X
  476. X        if (n < 0)
  477. X                return (forwline(f, -n));
  478. X
  479. X
  480. X    /* if we are on the last line as we start....fail the command */
  481. X    if (lback(curwp->w_dotp) == curbp->b_linep)
  482. X        return(FALSE);
  483. X
  484. X    /* if the last command was not note a line move,
  485. X       reset the goal column */
  486. X        if ((lastflag&CFCPCN) == 0)
  487. X                curgoal = getccol(FALSE);
  488. X
  489. X    /* flag this command as a line move */
  490. X        thisflag |= CFCPCN;
  491. X
  492. X    /* and move the point up */
  493. X        dlp = curwp->w_dotp;
  494. X        while (n-- && lback(dlp)!=curbp->b_linep)
  495. X                dlp = lback(dlp);
  496. X
  497. X    /* reseting the current position */
  498. X        curwp->w_dotp  = dlp;
  499. X        curwp->w_doto  = getgoal(dlp);
  500. X        curwp->w_flag |= WFMOVE;
  501. X        return (TRUE);
  502. X}
  503. X
  504. X#if    WORDPRO
  505. Xgotobop(f, n)    /* go back to the beginning of the current paragraph
  506. X           here we look for a <NL><NL> or <NL><TAB> or <NL><SPACE>
  507. X           combination to delimit the beginning of a paragraph    */
  508. X
  509. Xint f, n;    /* default Flag & Numeric argument */
  510. X
  511. X{
  512. X    register int suc;    /* success of last backchar */
  513. X
  514. X    if (n < 0)    /* the other way...*/
  515. X        return(gotoeop(f, -n));
  516. X
  517. X    while (n-- > 0) {    /* for each one asked for */
  518. X
  519. X        /* first scan back until we are in a word */
  520. X        suc = backchar(FALSE, 1);
  521. X        while (!inword() && suc)
  522. X            suc = backchar(FALSE, 1);
  523. X        curwp->w_doto = 0;    /* and go to the B-O-Line */
  524. X
  525. X        /* and scan back until we hit a <NL><NL> or <NL><TAB>
  526. X           or a <NL><SPACE>                    */
  527. X        while (lback(curwp->w_dotp) != curbp->b_linep)
  528. X            if (llength(curwp->w_dotp) != 0 &&
  529. X                lgetc(curwp->w_dotp, curwp->w_doto) != TAB &&
  530. X                lgetc(curwp->w_dotp, curwp->w_doto) != ' ')
  531. X                curwp->w_dotp = lback(curwp->w_dotp);
  532. X            else
  533. X                break;
  534. X
  535. X        /* and then forward until we are in a word */
  536. X        suc = forwchar(FALSE, 1);
  537. X        while (suc && !inword())
  538. X            suc = forwchar(FALSE, 1);
  539. X    }
  540. X    curwp->w_flag |= WFMOVE;    /* force screen update */
  541. X    return(TRUE);
  542. X}
  543. X
  544. Xgotoeop(f, n)    /* go forword to the end of the current paragraph
  545. X           here we look for a <NL><NL> or <NL><TAB> or <NL><SPACE>
  546. X           combination to delimit the beginning of a paragraph    */
  547. X
  548. Xint f, n;    /* default Flag & Numeric argument */
  549. X
  550. X{
  551. X    register int suc;    /* success of last backchar */
  552. X
  553. X    if (n < 0)    /* the other way...*/
  554. X        return(gotobop(f, -n));
  555. X
  556. X    while (n-- > 0) {    /* for each one asked for */
  557. X
  558. X        /* first scan forward until we are in a word */
  559. X        suc = forwchar(FALSE, 1);
  560. X        while (!inword() && suc)
  561. X            suc = forwchar(FALSE, 1);
  562. X        curwp->w_doto = 0;    /* and go to the B-O-Line */
  563. X        if (suc)    /* of next line if not at EOF */
  564. X            curwp->w_dotp = lforw(curwp->w_dotp);
  565. X
  566. X        /* and scan forword until we hit a <NL><NL> or <NL><TAB>
  567. X           or a <NL><SPACE>                    */
  568. X        while (curwp->w_dotp != curbp->b_linep) {
  569. X            if (llength(curwp->w_dotp) != 0 &&
  570. X                lgetc(curwp->w_dotp, curwp->w_doto) != TAB &&
  571. X                lgetc(curwp->w_dotp, curwp->w_doto) != ' ')
  572. X                curwp->w_dotp = lforw(curwp->w_dotp);
  573. X            else
  574. X                break;
  575. X        }
  576. X
  577. X        /* and then backward until we are in a word */
  578. X        suc = backchar(FALSE, 1);
  579. X        while (suc && !inword()) {
  580. X            suc = backchar(FALSE, 1);
  581. X        }
  582. X        curwp->w_doto = llength(curwp->w_dotp);    /* and to the EOL */
  583. X    }
  584. X    curwp->w_flag |= WFMOVE;    /* force screen update */
  585. X    return(TRUE);
  586. X}
  587. X#endif
  588. X
  589. X/*
  590. X * This routine, given a pointer to a LINE, and the current cursor goal
  591. X * column, return the best choice for the offset. The offset is returned.
  592. X * Used by "C-N" and "C-P".
  593. X */
  594. Xgetgoal(dlp)
  595. Xregister LINE   *dlp;
  596. X{
  597. X        register int    c;
  598. X        register int    col;
  599. X        register int    newcol;
  600. X        register int    dbo;
  601. X
  602. X        col = 0;
  603. X        dbo = 0;
  604. X        while (dbo != llength(dlp)) {
  605. X                c = lgetc(dlp, dbo);
  606. X                newcol = col;
  607. X                if (c == '\t')
  608. X                        newcol |= 0x07;
  609. X                else if (c<0x20 || c==0x7F)
  610. X                        ++newcol;
  611. X                ++newcol;
  612. X                if (newcol > curgoal)
  613. X                        break;
  614. X                col = newcol;
  615. X                ++dbo;
  616. X        }
  617. X        return (dbo);
  618. X}
  619. X
  620. X/*
  621. X * Scroll forward by a specified number of lines, or by a full page if no
  622. X * argument. Bound to "C-V". The "2" in the arithmetic on the window size is
  623. X * the overlap; this value is the default overlap value in ITS EMACS. Because
  624. X * this zaps the top line in the display window, we have to do a hard update.
  625. X */
  626. Xforwpage(f, n)
  627. Xregister int    n;
  628. X{
  629. X        register LINE   *lp;
  630. X
  631. X        if (f == FALSE) {
  632. X                n = curwp->w_ntrows - 2;        /* Default scroll.      */
  633. X                if (n <= 0)                     /* Forget the overlap   */
  634. X                        n = 1;                  /* if tiny window.      */
  635. X        } else if (n < 0)
  636. X                return (backpage(f, -n));
  637. X#if     CVMVAS
  638. X        else                                    /* Convert from pages   */
  639. X                n *= curwp->w_ntrows;           /* to lines.            */
  640. X#endif
  641. X        lp = curwp->w_linep;
  642. X        while (n-- && lp!=curbp->b_linep)
  643. X                lp = lforw(lp);
  644. X        curwp->w_linep = lp;
  645. X        curwp->w_dotp  = lp;
  646. X        curwp->w_doto  = 0;
  647. X        curwp->w_flag |= WFHARD;
  648. X        return (TRUE);
  649. X}
  650. X
  651. X/*
  652. X * This command is like "forwpage", but it goes backwards. The "2", like
  653. X * above, is the overlap between the two windows. The value is from the ITS
  654. X * EMACS manual. Bound to "M-V". We do a hard update for exactly the same
  655. X * reason.
  656. X */
  657. Xbackpage(f, n)
  658. Xregister int    n;
  659. X{
  660. X        register LINE   *lp;
  661. X
  662. X        if (f == FALSE) {
  663. X                n = curwp->w_ntrows - 2;        /* Default scroll.      */
  664. X                if (n <= 0)                     /* Don't blow up if the */
  665. X                        n = 1;                  /* window is tiny.      */
  666. X        } else if (n < 0)
  667. X                return (forwpage(f, -n));
  668. X#if     CVMVAS
  669. X        else                                    /* Convert from pages   */
  670. X                n *= curwp->w_ntrows;           /* to lines.            */
  671. X#endif
  672. X        lp = curwp->w_linep;
  673. X        while (n-- && lback(lp)!=curbp->b_linep)
  674. X                lp = lback(lp);
  675. X        curwp->w_linep = lp;
  676. X        curwp->w_dotp  = lp;
  677. X        curwp->w_doto  = 0;
  678. X        curwp->w_flag |= WFHARD;
  679. X        return (TRUE);
  680. X}
  681. X
  682. X/*
  683. X * Set the mark in the current window to the value of "." in the window. No
  684. X * errors are possible. Bound to "M-.".
  685. X */
  686. Xsetmark(f, n)
  687. X{
  688. X        curwp->w_markp = curwp->w_dotp;
  689. X        curwp->w_marko = curwp->w_doto;
  690. X        mlwrite("[Mark set]");
  691. X        return (TRUE);
  692. X}
  693. X
  694. X/*
  695. X * Swap the values of "." and "mark" in the current window. This is pretty
  696. X * easy, bacause all of the hard work gets done by the standard routine
  697. X * that moves the mark about. The only possible error is "no mark". Bound to
  698. X * "C-X C-X".
  699. X */
  700. Xswapmark(f, n)
  701. X{
  702. X        register LINE   *odotp;
  703. X        register int    odoto;
  704. X
  705. X        if (curwp->w_markp == NULL) {
  706. X                mlwrite("No mark in this window");
  707. X                return (FALSE);
  708. X        }
  709. X        odotp = curwp->w_dotp;
  710. X        odoto = curwp->w_doto;
  711. X        curwp->w_dotp  = curwp->w_markp;
  712. X        curwp->w_doto  = curwp->w_marko;
  713. X        curwp->w_markp = odotp;
  714. X        curwp->w_marko = odoto;
  715. X        curwp->w_flag |= WFMOVE;
  716. X        return (TRUE);
  717. X}
  718. FRIDAY_NIGHT
  719. echo extracting - bind.c
  720. sed 's/^X//' > bind.c << 'FRIDAY_NIGHT'
  721. X/*    This file is for functions having to do with key bindings,
  722. X    descriptions, help commands and startup file.
  723. X
  724. X    written 11-feb-86 by Daniel Lawrence
  725. X                                */
  726. X
  727. X#include    <stdio.h>
  728. X#include    "estruct.h"
  729. X#include    "edef.h"
  730. X#include    "epath.h"
  731. X
  732. Xextern int meta(), cex(), unarg(), ctrlg(); /* dummy prefix binding functions */
  733. X
  734. Xhelp(f, n)    /* give me some help!!!!
  735. X           bring up a fake buffer and read the help file
  736. X           into it with view mode            */
  737. X{
  738. X    register WINDOW *wp;    /* scaning pointer to windows */
  739. X    register BUFFER *bp;    /* buffer pointer to help */
  740. X    char *fname;        /* ptr to file returned by flook() */
  741. X
  742. X    /* first check if we are already here */
  743. X    bp = bfind("emacs.hlp", FALSE, BFINVS);
  744. X
  745. X    if (bp == NULL) {
  746. X        fname = flook(pathname[1], FALSE);
  747. X        if (fname == NULL) {
  748. X            mlwrite("[Help file is not online]");
  749. X            return(FALSE);
  750. X        }
  751. X    }
  752. X
  753. X    /* split the current window to make room for the help stuff */
  754. X    if (splitwind(FALSE, 1) == FALSE)
  755. X            return(FALSE);
  756. X
  757. X    if (bp == NULL) {
  758. X        /* and read the stuff in */
  759. X        if (getfile(fname, FALSE) == FALSE)
  760. X            return(FALSE);
  761. X    } else
  762. X        swbuffer(bp);
  763. X
  764. X    /* make this window in VIEW mode, update all mode lines */
  765. X    curwp->w_bufp->b_mode |= MDVIEW;
  766. X    curwp->w_bufp->b_flag |= BFINVS;
  767. X    wp = wheadp;
  768. X    while (wp != NULL) {
  769. X        wp->w_flag |= WFMODE;
  770. X        wp = wp->w_wndp;
  771. X    }
  772. X    return(TRUE);
  773. X}
  774. X
  775. Xdeskey(f, n)    /* describe the command for a certain key */
  776. X
  777. X{
  778. X    register int c;        /* key to describe */
  779. X    register char *ptr;    /* string pointer to scan output strings */
  780. X    char outseq[NSTRING];    /* output buffer for command sequence */
  781. X    int (*getbind())();
  782. X
  783. X    /* prompt the user to type us a key to describe */
  784. X    mlwrite(": describe-key ");
  785. X
  786. X    /* get the command sequence to describe
  787. X       change it to something we can print as well */
  788. X    cmdstr(c = getckey(FALSE), &outseq[0]);
  789. X
  790. X    /* and dump it out */
  791. X    ostring(outseq);
  792. X    ostring(" ");
  793. X
  794. X    /* find the right ->function */
  795. X    if ((ptr = getfname(getbind(c))) == NULL)
  796. X        ptr = "Not Bound";
  797. X
  798. X    /* output the command sequence */
  799. X    ostring(ptr);
  800. X}
  801. X
  802. X/* bindtokey:    add a new key to the key binding table        */
  803. X
  804. Xbindtokey(f, n)
  805. X
  806. Xint f, n;    /* command arguments [IGNORED] */
  807. X
  808. X{
  809. X    register unsigned int c;/* command key to bind */
  810. X    register int (*kfunc)();/* ptr to the requested function to bind to */
  811. X    register KEYTAB *ktp;    /* pointer into the command table */
  812. X    register int found;    /* matched command flag */
  813. X    char outseq[80];    /* output buffer for keystroke sequence */
  814. X    int (*getname())();
  815. X
  816. X    /* prompt the user to type in a key to bind */
  817. X    mlwrite(": bind-to-key ");
  818. X
  819. X    /* get the function name to bind it to */
  820. X    kfunc = getname();
  821. X    if (kfunc == NULL) {
  822. X        mlwrite("[No such function]");
  823. X        return(FALSE);
  824. X    }
  825. X    ostring(" ");
  826. X
  827. X    /* get the command sequence to bind */
  828. X    c = getckey((kfunc == meta) || (kfunc == cex) ||
  829. X                (kfunc == unarg) || (kfunc == ctrlg));
  830. X
  831. X    /* change it to something we can print as well */
  832. X    cmdstr(c, &outseq[0]);
  833. X
  834. X    /* and dump it out */
  835. X    ostring(outseq);
  836. X
  837. X    /* if the function is a prefix key */
  838. X    if (kfunc == meta || kfunc == cex ||
  839. X        kfunc == unarg || kfunc == ctrlg) {
  840. X
  841. X        /* search for an existing binding for the prefix key */
  842. X        ktp = &keytab[0];
  843. X        found = FALSE;
  844. X        while (ktp->k_fp != NULL) {
  845. X            if (ktp->k_fp == kfunc)
  846. X                unbindchar(ktp->k_code);
  847. X            ++ktp;
  848. X        }
  849. X
  850. X        /* reset the appropriate global prefix variable */
  851. X        if (kfunc == meta)
  852. X            metac = c;
  853. X        if (kfunc == cex)
  854. X            ctlxc = c;
  855. X        if (kfunc == unarg)
  856. X            reptc = c;
  857. X        if (kfunc == ctrlg)
  858. X            abortc = c;
  859. X    }
  860. X
  861. X    /* search the table to see if it exists */
  862. X    ktp = &keytab[0];
  863. X    found = FALSE;
  864. X    while (ktp->k_fp != NULL) {
  865. X        if (ktp->k_code == c) {
  866. X            found = TRUE;
  867. X            break;
  868. X        }
  869. X        ++ktp;
  870. X    }
  871. X
  872. X    if (found) {    /* it exists, just change it then */
  873. X        ktp->k_fp = kfunc;
  874. X    } else {    /* otherwise we need to add it to the end */
  875. X        /* if we run out of binding room, bitch */
  876. X        if (ktp >= &keytab[NBINDS]) {
  877. X            mlwrite("Binding table FULL!");
  878. X            return(FALSE);
  879. X        }
  880. X
  881. X        ktp->k_code = c;    /* add keycode */
  882. X        ktp->k_fp = kfunc;    /* and the function pointer */
  883. X        ++ktp;            /* and make sure the next is null */
  884. X        ktp->k_code = 0;
  885. X        ktp->k_fp = NULL;
  886. X    }
  887. X    return(TRUE);
  888. X}
  889. X
  890. X/* unbindkey:    delete a key from the key binding table    */
  891. X
  892. Xunbindkey(f, n)
  893. X
  894. Xint f, n;    /* command arguments [IGNORED] */
  895. X
  896. X{
  897. X    register int c;        /* command key to unbind */
  898. X    char outseq[80];    /* output buffer for keystroke sequence */
  899. X
  900. X    /* prompt the user to type in a key to unbind */
  901. X    mlwrite(": unbind-key ");
  902. X
  903. X    /* get the command sequence to unbind */
  904. X    c = getckey(FALSE);        /* get a command sequence */
  905. X
  906. X    /* change it to something we can print as well */
  907. X    cmdstr(c, &outseq[0]);
  908. X
  909. X    /* and dump it out */
  910. X    ostring(outseq);
  911. X
  912. X    /* if it isn't bound, bitch */
  913. X    if (unbindchar(c) == FALSE) {
  914. X        mlwrite("[Key not bound]");
  915. X        return(FALSE);
  916. X    }
  917. X    return(TRUE);
  918. X}
  919. X
  920. Xunbindchar(c)
  921. X
  922. Xint c;        /* command key to unbind */
  923. X
  924. X{
  925. X    register KEYTAB *ktp;    /* pointer into the command table */
  926. X    register KEYTAB *sktp;    /* saved pointer into the command table */
  927. X    register int found;    /* matched command flag */
  928. X
  929. X    /* search the table to see if the key exists */
  930. X    ktp = &keytab[0];
  931. X    found = FALSE;
  932. X    while (ktp->k_fp != NULL) {
  933. X        if (ktp->k_code == c) {
  934. X            found = TRUE;
  935. X            break;
  936. X        }
  937. X        ++ktp;
  938. X    }
  939. X
  940. X    /* if it isn't bound, bitch */
  941. X    if (!found)
  942. X        return(FALSE);
  943. X
  944. X    /* save the pointer and scan to the end of the table */
  945. X    sktp = ktp;
  946. X    while (ktp->k_fp != NULL)
  947. X        ++ktp;
  948. X    --ktp;        /* backup to the last legit entry */
  949. X
  950. X    /* copy the last entry to the current one */
  951. X    sktp->k_code = ktp->k_code;
  952. X    sktp->k_fp   = ktp->k_fp;
  953. X
  954. X    /* null out the last one */
  955. X    ktp->k_code = 0;
  956. X    ktp->k_fp = NULL;
  957. X    return(TRUE);
  958. X}
  959. X
  960. Xdesbind(f, n)    /* describe bindings
  961. X           bring up a fake buffer and list the key bindings
  962. X           into it with view mode            */
  963. X
  964. X#if    APROP
  965. X{
  966. X    buildlist(TRUE, "");
  967. X}
  968. X
  969. Xapro(f, n)    /* Apropos (List functions that match a substring) */
  970. X
  971. X{
  972. X    char mstring[NSTRING];    /* string to match cmd names to */
  973. X    int status;        /* status return */
  974. X
  975. X    status = mlreply("Apropos string: ", mstring, NSTRING - 1);
  976. X    if (status != TRUE)
  977. X        return(status);
  978. X
  979. X    return(buildlist(FALSE, mstring));
  980. X}
  981. X
  982. Xbuildlist(type, mstring)  /* build a binding list (limited or full) */
  983. X
  984. Xint type;    /* true = full list,   false = partial list */
  985. Xchar *mstring;    /* match string if a partial list */
  986. X
  987. X#endif
  988. X{
  989. X#if    ST520 & LATTICE
  990. X#define    register        
  991. X#endif
  992. X    register WINDOW *wp;    /* scanning pointer to windows */
  993. X    register KEYTAB *ktp;    /* pointer into the command table */
  994. X    register NBIND *nptr;    /* pointer into the name binding table */
  995. X    register BUFFER *bp;    /* buffer to put binding list into */
  996. X    char *strp;        /* pointer int string to send */
  997. X    int cpos;        /* current position to use in outseq */
  998. X    char outseq[80];    /* output buffer for keystroke sequence */
  999. X
  1000. X    /* split the current window to make room for the binding list */
  1001. X    if (splitwind(FALSE, 1) == FALSE)
  1002. X            return(FALSE);
  1003. X
  1004. X    /* and get a buffer for it */
  1005. X    bp = bfind("Binding list", TRUE, 0);
  1006. X    if (bp == NULL || bclear(bp) == FALSE) {
  1007. X        mlwrite("Can not display binding list");
  1008. X        return(FALSE);
  1009. X    }
  1010. X
  1011. X    /* let us know this is in progress */
  1012. X    mlwrite("[Building binding list]");
  1013. X
  1014. X    /* disconect the current buffer */
  1015. X        if (--curbp->b_nwnd == 0) {             /* Last use.            */
  1016. X                curbp->b_dotp  = curwp->w_dotp;
  1017. X                curbp->b_doto  = curwp->w_doto;
  1018. X                curbp->b_markp = curwp->w_markp;
  1019. X                curbp->b_marko = curwp->w_marko;
  1020. X        }
  1021. X
  1022. X    /* connect the current window to this buffer */
  1023. X    curbp = bp;    /* make this buffer current in current window */
  1024. X    bp->b_mode = 0;        /* no modes active in binding list */
  1025. X    bp->b_nwnd++;        /* mark us as more in use */
  1026. X    wp = curwp;
  1027. X    wp->w_bufp = bp;
  1028. X    wp->w_linep = bp->b_linep;
  1029. X    wp->w_flag = WFHARD|WFFORCE;
  1030. X    wp->w_dotp = bp->b_dotp;
  1031. X    wp->w_doto = bp->b_doto;
  1032. X    wp->w_markp = NULL;
  1033. X    wp->w_marko = 0;
  1034. X
  1035. X    /* build the contents of this window, inserting it line by line */
  1036. X    nptr = &names[0];
  1037. X    while (nptr->n_func != NULL) {
  1038. X
  1039. X        /* add in the command name */
  1040. X        strcpy(outseq, nptr->n_name);
  1041. X        cpos = strlen(outseq);
  1042. X        
  1043. X#if    APROP
  1044. X        /* if we are executing an apropos command..... */
  1045. X        if (type == FALSE &&
  1046. X            /* and current string doesn't include the search string */
  1047. X            strinc(outseq, mstring) == FALSE)
  1048. X            goto fail;
  1049. X#endif
  1050. X        /* search down any keys bound to this */
  1051. X        ktp = &keytab[0];
  1052. X        while (ktp->k_fp != NULL) {
  1053. X            if (ktp->k_fp == nptr->n_func) {
  1054. X                /* padd out some spaces */
  1055. X                while (cpos < 25)
  1056. X                    outseq[cpos++] = ' ';
  1057. X
  1058. X                /* add in the command sequence */
  1059. X                cmdstr(ktp->k_code, &outseq[cpos]);
  1060. X                strcat(outseq, "\n");
  1061. X
  1062. X                /* and add it as a line into the buffer */
  1063. X                if (linstr(outseq) != TRUE)
  1064. X                    return(FALSE);
  1065. X
  1066. X                cpos = 0;    /* and clear the line */
  1067. X            }
  1068. X            ++ktp;
  1069. X        }
  1070. X
  1071. X        /* if no key was bound, we need to dump it anyway */
  1072. X        if (cpos > 0) {
  1073. X            outseq[cpos++] = '\n';
  1074. X            outseq[cpos] = 0;
  1075. X            if (linstr(outseq) != TRUE)
  1076. X                return(FALSE);
  1077. X        }
  1078. X
  1079. Xfail:        /* and on to the next name */
  1080. X        ++nptr;
  1081. X    }
  1082. X
  1083. X    curwp->w_bufp->b_mode |= MDVIEW;/* put this buffer view mode */
  1084. X    curbp->b_flag &= ~BFCHG;    /* don't flag this as a change */
  1085. X    wp->w_dotp = lforw(bp->b_linep);/* back to the beginning */
  1086. X    wp->w_doto = 0;
  1087. X    wp = wheadp;            /* and update ALL mode lines */
  1088. X    while (wp != NULL) {
  1089. X        wp->w_flag |= WFMODE;
  1090. X        wp = wp->w_wndp;
  1091. X    }
  1092. X    mlwrite("");    /* clear the mode line */
  1093. X    return(TRUE);
  1094. X}
  1095. X
  1096. X#if    APROP
  1097. Xstrinc(source, sub)    /* does source include sub? */
  1098. X
  1099. Xchar *source;    /* string to search in */
  1100. Xchar *sub;    /* substring to look for */
  1101. X
  1102. X{
  1103. X    char *sp;    /* ptr into source */
  1104. X    char *nxtsp;    /* next ptr into source */
  1105. X    char *tp;    /* ptr into substring */
  1106. X
  1107. X    /* for each character in the source string */
  1108. X    sp = source;
  1109. X    while (*sp) {
  1110. X        tp = sub;
  1111. X        nxtsp = sp;
  1112. X
  1113. X        /* is the substring here? */
  1114. X        while (*tp) {
  1115. X            if (*nxtsp++ != *tp)
  1116. X                break;
  1117. X            else
  1118. X                tp++;
  1119. X        }
  1120. X
  1121. X        /* yes, return a success */
  1122. X        if (*tp == 0)
  1123. X            return(TRUE);
  1124. X
  1125. X        /* no, onward */
  1126. X        sp++;
  1127. X    }
  1128. X    return(FALSE);
  1129. X}
  1130. X#endif
  1131. X
  1132. X/* get a command key sequence from the keyboard    */
  1133. X
  1134. Xunsigned int getckey(mflag)
  1135. X
  1136. Xint mflag;    /* going for a meta sequence? */
  1137. X
  1138. X{
  1139. X    register unsigned int c;    /* character fetched */
  1140. X    char tok[NSTRING];        /* command incoming */
  1141. X
  1142. X    /* check to see if we are executing a command line */
  1143. X    if (clexec) {
  1144. X        macarg(tok);    /* get the next token */
  1145. X        return(stock(tok));
  1146. X    }
  1147. X
  1148. X    /* or the normal way */
  1149. X    if (mflag)
  1150. X        c = get1key();
  1151. X    else
  1152. X        c = getcmd();
  1153. X    return(c);
  1154. X}
  1155. X
  1156. X/* execute the startup file */
  1157. X
  1158. Xstartup(sfname)
  1159. X
  1160. Xchar *sfname;    /* name of startup file (null if default) */
  1161. X
  1162. X{
  1163. X    char *fname;    /* resulting file name to execute */
  1164. X
  1165. X    /* look up the startup file */
  1166. X    if (*sfname != 0)
  1167. X        fname = flook(sfname, TRUE);
  1168. X    else
  1169. X        fname = flook(pathname[0], TRUE);
  1170. X
  1171. X    /* if it isn't around, don't sweat it */
  1172. X    if (fname == NULL)
  1173. X        return(TRUE);
  1174. X
  1175. X    /* otherwise, execute the sucker */
  1176. X    return(dofile(fname));
  1177. X}
  1178. X
  1179. X/*    Look up the existance of a file along the normal or PATH
  1180. X    environment variable. Look first in the HOME directory if
  1181. X    asked and possible
  1182. X*/
  1183. X
  1184. Xchar *flook(fname, hflag)
  1185. X
  1186. Xchar *fname;    /* base file name to search for */
  1187. Xint hflag;    /* Look in the HOME environment variable first? */
  1188. X
  1189. X{
  1190. X    register char *home;    /* path to home directory */
  1191. X    register char *path;    /* environmental PATH variable */
  1192. X    register char *sp;    /* pointer into path spec */
  1193. X    register int i;        /* index */
  1194. X    static char fspec[NSTRING];    /* full path spec to search */
  1195. X    char *getenv();
  1196. X
  1197. X#if    ENVFUNC
  1198. X
  1199. X    if (hflag) {
  1200. X        home = getenv("HOME");
  1201. X        if (home != NULL) {
  1202. X            /* build home dir file spec */
  1203. X            strcpy(fspec, home);
  1204. X            strcat(fspec, "/");
  1205. X            strcat(fspec, fname);
  1206. X
  1207. X            /* and try it out */
  1208. X            if (ffropen(fspec) == FIOSUC) {
  1209. X                ffclose();
  1210. X                return(fspec);
  1211. X            }
  1212. X        }
  1213. X    }
  1214. X#endif
  1215. X
  1216. X    /* always try the current directory first */
  1217. X    if (ffropen(fname) == FIOSUC) {
  1218. X        ffclose();
  1219. X        return(fname);
  1220. X    }
  1221. X
  1222. X#if    ENVFUNC
  1223. X    /* get the PATH variable */
  1224. X    path = getenv("PATH");
  1225. X    if (path != NULL)
  1226. X        while (*path) {
  1227. X
  1228. X            /* build next possible file spec */
  1229. X            sp = fspec;
  1230. X#if    ST520 & MWC
  1231. X            while (*path && (*path != PATHCHR) && (*path != ','))
  1232. X#else
  1233. X            while (*path && (*path != PATHCHR))
  1234. X#endif
  1235. X                *sp++ = *path++;
  1236. X
  1237. X            /* add a terminating dir separator if we need it */
  1238. X            if (sp != fspec)
  1239. X#if    ST520
  1240. X                *sp++ = '\\';
  1241. X#else
  1242. X                *sp++ = '/';
  1243. X#endif
  1244. X            *sp = 0;
  1245. X            strcat(fspec, fname);
  1246. X
  1247. X            /* and try it out */
  1248. X            if (ffropen(fspec) == FIOSUC) {
  1249. X                ffclose();
  1250. X                return(fspec);
  1251. X            }
  1252. X
  1253. X#if    ST520 & MWC
  1254. X            if ((*path == PATHCHR) || (*path == ','))
  1255. X#else
  1256. X            if (*path == PATHCHR)
  1257. X#endif
  1258. X                ++path;
  1259. X        }
  1260. X#endif
  1261. X
  1262. X    /* look it up via the old table method */
  1263. X    for (i=2; i < NPNAMES; i++) {
  1264. X        strcpy(fspec, pathname[i]);
  1265. X        strcat(fspec, fname);
  1266. X
  1267. X        /* and try it out */
  1268. X        if (ffropen(fspec) == FIOSUC) {
  1269. X            ffclose();
  1270. X            return(fspec);
  1271. X        }
  1272. X    }
  1273. X
  1274. X    return(NULL);    /* no such luck */
  1275. X}
  1276. X
  1277. Xcmdstr(c, seq)    /* change a key command to a string we can print out */
  1278. X
  1279. Xint c;        /* sequence to translate */
  1280. Xchar *seq;    /* destination string for sequence */
  1281. X
  1282. X{
  1283. X    char *ptr;    /* pointer into current position in sequence */
  1284. X
  1285. X    ptr = seq;
  1286. X
  1287. X    /* apply meta sequence if needed */
  1288. X    if (c & META) {
  1289. X        *ptr++ = 'M';
  1290. X        *ptr++ = '-';
  1291. X    }
  1292. X
  1293. X    /* apply ^X sequence if needed */
  1294. X    if (c & CTLX) {
  1295. X        *ptr++ = '^';
  1296. X        *ptr++ = 'X';
  1297. X    }
  1298. X
  1299. X    /* apply SPEC sequence if needed */
  1300. X    if (c & SPEC) {
  1301. X        *ptr++ = 'F';
  1302. X        *ptr++ = 'N';
  1303. X    }
  1304. X
  1305. X    /* apply control sequence if needed */
  1306. X    if (c & CTRL) {
  1307. X        *ptr++ = '^';
  1308. X    }
  1309. X
  1310. X    c = c & 255;    /* strip the prefixes */
  1311. X
  1312. X    /* and output the final sequence */
  1313. X
  1314. X    *ptr++ = c;
  1315. X    *ptr = 0;    /* terminate the string */
  1316. X}
  1317. X
  1318. X/*    This function looks a key binding up in the binding table    */
  1319. X
  1320. Xint (*getbind(c))()
  1321. X
  1322. Xint c;    /* key to find what is bound to it */
  1323. X
  1324. X{
  1325. X    register KEYTAB *ktp;
  1326. X
  1327. X        ktp = &keytab[0];                       /* Look in key table.   */
  1328. X        while (ktp->k_fp != NULL) {
  1329. X                if (ktp->k_code == c)
  1330. X                        return(ktp->k_fp);
  1331. X                ++ktp;
  1332. X        }
  1333. X
  1334. X    /* no such binding */
  1335. X    return(NULL);
  1336. X}
  1337. X
  1338. X/* getfname:    This function takes a ptr to function and gets the name
  1339. X        associated with it
  1340. X*/
  1341. X
  1342. Xchar *getfname(func)
  1343. X
  1344. Xint (*func)();    /* ptr to the requested function to bind to */
  1345. X
  1346. X{
  1347. X    register NBIND *nptr;    /* pointer into the name binding table */
  1348. X
  1349. X    /* skim through the table, looking for a match */
  1350. X    nptr = &names[0];
  1351. X    while (nptr->n_func != NULL) {
  1352. X        if (nptr->n_func == func)
  1353. X            return(nptr->n_name);
  1354. X        ++nptr;
  1355. X    }
  1356. X    return(NULL);
  1357. X}
  1358. X
  1359. Xint (*fncmatch(fname))() /* match fname to a function in the names table
  1360. X                and return any match or NULL if none        */
  1361. X
  1362. Xchar *fname;    /* name to attempt to match */
  1363. X
  1364. X{
  1365. X    register NBIND *ffp;    /* pointer to entry in name binding table */
  1366. X
  1367. X    /* scan through the table, returning any match */
  1368. X    ffp = &names[0];
  1369. X    while (ffp->n_func != NULL) {
  1370. X        if (strcmp(fname, ffp->n_name) == 0)
  1371. X            return(ffp->n_func);
  1372. X        ++ffp;
  1373. X    }
  1374. X    return(NULL);
  1375. X}
  1376. X
  1377. X/* stock:    String key name TO Command Key        */
  1378. X
  1379. Xunsigned int stock(keyname)
  1380. X
  1381. Xchar *keyname;        /* name of key to translate to Command key form */
  1382. X
  1383. X{
  1384. X    register unsigned int c;    /* key sequence to return */
  1385. X
  1386. X    /* parse it up */
  1387. X    c = 0;
  1388. X
  1389. X    /* first, the META prefix */
  1390. X    if (*keyname == 'M' && *(keyname+1) == '-') {
  1391. X        c = META;
  1392. X        keyname += 2;
  1393. X    }
  1394. X
  1395. X    /* next the function prefix */
  1396. X    if (*keyname == 'F' && *(keyname+1) == 'N') {
  1397. X        c |= SPEC;
  1398. X        keyname += 2;
  1399. X    }
  1400. X
  1401. X    /* control-x as well... (but not with FN) */
  1402. X    if (*keyname == '^' && *(keyname+1) == 'X'&& !(c & SPEC)) {
  1403. X        c |= CTLX;
  1404. X        keyname += 2;
  1405. X    }
  1406. X
  1407. X    /* a control char? */
  1408. X    if (*keyname == '^' && *(keyname+1) != 0) {
  1409. X        c |= CTRL;
  1410. X        ++keyname;
  1411. X    }
  1412. X    if (*keyname < 32) {
  1413. X        c |= CTRL;
  1414. X        *keyname += 'A';
  1415. X    }
  1416. X
  1417. X
  1418. X    /* make sure we are not lower case (not with function keys)*/
  1419. X    if (*keyname >= 'a' && *keyname <= 'z' && !(c & SPEC))
  1420. X        *keyname -= 32;
  1421. X
  1422. X    /* the final sequence... */
  1423. X    c |= *keyname;
  1424. X    return(c);
  1425. X}
  1426. X
  1427. Xchar *transbind(skey)    /* string key name to binding name.... */
  1428. X
  1429. Xchar *skey;    /* name of keey to get binding for */
  1430. X
  1431. X{
  1432. X    char *bindname;
  1433. X    unsigned int stock();
  1434. X    int (*getbind())();
  1435. X
  1436. X    bindname = getfname(getbind(stock(skey)));
  1437. X    if (bindname == NULL)
  1438. X        bindname = "ERROR";
  1439. X
  1440. X    return(bindname);
  1441. X}
  1442. FRIDAY_NIGHT
  1443. echo mes.1 completed!
  1444. # That's all folks!
  1445.  
  1446.  
  1447.