home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume1 / 8711 / microemacs-3.9 / 1 next >
Internet Message Format  |  1991-03-12  |  35KB

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