home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3491 < prev    next >
Internet Message Format  |  1991-06-19  |  56KB

  1. From: pgf@cayman.COM (Paul Fox)
  2. Newsgroups: alt.sources
  3. Subject: Vile 01/17 - vi feel-alike (multi-window)
  4. Message-ID: <4520@cayman.COM>
  5. Date: 7 Jun 91 22:09:05 GMT
  6.  
  7. #!/bin/sh
  8. # This is Vile, a shell archive (shar 3.47)
  9. # made 06/07/1991 22:01 UTC by pgf@cayman.com
  10. # Source directory /tmp_mnt/home/carl/pgf/vile
  11. #
  12. # existing files WILL be overwritten
  13. #
  14. # This is part 1 of a multipart archive                                    
  15. # do not concatenate these parts, unpack them in order with /bin/sh        
  16. #
  17. # This shar contains:
  18. # length  mode       name
  19. # ------ ---------- ------------------------------------------
  20. #   3835 -r--r--r-- README
  21. #   6488 -r--r--r-- ansi.c
  22. #   4175 -r--r--r-- at386.c
  23. #  20335 -r--r--r-- basic.c
  24. #  21479 -r--r--r-- bind.c
  25. #  20200 -r--r--r-- buffer.c
  26. #   6009 -r--r--r-- buglist
  27. #  17753 -r--r--r-- cmdtbl
  28. #   6989 -r--r--r-- crypt.c
  29. #   2171 -r--r--r-- csrch.c
  30. #   3333 -r--r--r-- dg10.c
  31. #  40087 -r--r--r-- display.c
  32. #   4340 -r--r--r-- dolock.c
  33. #  14722 -r--r--r-- ebind.h
  34. #   9852 -r--r--r-- edef.h
  35. #  27465 -r--r--r-- efunc.h
  36. #    956 -r--r--r-- epath.h
  37. #  30449 -r--r--r-- estruct.h
  38. #  18430 -r--r--r-- eval.c
  39. #   5247 -r--r--r-- evar.h
  40. #  32572 -r--r--r-- exec.c
  41. #  28527 -r--r--r-- file.c
  42. #   7384 -r--r--r-- fileio.c
  43. #   3373 -r--r--r-- finderr.c
  44. #   2834 -r--r--r-- globals.c
  45. #   3750 -r--r--r-- hp110.c
  46. #   9245 -r--r--r-- hp150.c
  47. #  10074 -r--r--r-- ibmpc.c
  48. #  10225 -r--r--r-- input.c
  49. #  18075 -r--r--r-- isearch.c
  50. #  20714 -r--r--r-- line.c
  51. #   3557 -r--r--r-- lock.c
  52. #  23507 -r--r--r-- main.c
  53. #   1438 -r--r--r-- make.ini
  54. #   9302 -r--r--r-- makefile
  55. #   7809 -r--r--r-- mktbls.c
  56. #   5332 -rw-rw-r-- nebind.h
  57. #  19211 -rw-rw-r-- nefunc.h
  58. #  17247 -rw-rw-r-- nename.h
  59. #   5376 -r--r--r-- news.c
  60. #  19928 -r--r--r-- news.cps
  61. #   2848 -r--r--r-- npopen.c
  62. #   4253 -r--r--r-- oneliner.c
  63. #   4699 -r--r--r-- opers.c
  64. #  34147 -r--r--r-- random.c
  65. #   7014 -r--r--r-- readme.news
  66. #   9127 -r--r--r-- region.c
  67. #  35047 -r--r--r-- search.c
  68. #   7910 -r--r--r-- shorten/COPYING
  69. #    178 -r--r--r-- shorten/defines.c
  70. #    857 -r--r--r-- shorten/dups.c
  71. #    674 -r--r--r-- shorten/header.h
  72. #   1637 -r--r--r-- shorten/names.c
  73. #    220 -r--r--r-- shorten/reserved
  74. #      0 -r--r--r-- shorten/special
  75. #  20300 -r--r--r-- spawn.c
  76. #  19931 -r--r--r-- st520.c
  77. #  57909 -r--r--r-- tags
  78. #   7806 -r--r--r-- tags.c
  79. #   6065 -r--r--r-- tcap.c
  80. #  16097 -r--r--r-- termio.c
  81. #   5308 -r--r--r-- tipc.c
  82. #  11158 -r--r--r-- undo.c
  83. #  24385 -r--r--r-- vile.hlp
  84. #   6798 -r--r--r-- vmalloc.c
  85. #   9271 -r--r--r-- vmsvt.c
  86. #   3386 -r--r--r-- vt52.c
  87. #  20419 -r--r--r-- window.c
  88. #  10449 -r--r--r-- word.c
  89. #   6094 -r--r--r-- wordmov.c
  90. #    652 -r--r--r-- z100bios.asm
  91. #   7806 -r--r--r-- z309.c
  92. #
  93. if test -r _shar_seq_.tmp; then
  94.     echo 'Must unpack archives in sequence!'
  95.     echo Please unpack part `cat _shar_seq_.tmp` next
  96.     exit 1
  97. fi
  98. # ============= README ==============
  99. echo 'x - extracting README (Text)'
  100. sed 's/^X//' << 'SHAR_EOF' > 'README' &&
  101. X
  102. X
  103. X
  104. VILE -- VI Like Emacs: a vi workalike put together from Micro-Emacs by Paul Fox
  105. -------------------------------------------------------------------------------
  106. X
  107. X    This editor grew out of a frustration that although lots of
  108. X    eager programmers have tackled rewrites of Emacs, with new and
  109. X    better features (not to mention free source), I've not seen
  110. X    anything similar done with the Second True Editor.  (The
  111. X    First, of course, being /bin/ed)
  112. X
  113. X    So I took a copy of MicroEmacs 3.9 (which I've since
  114. X    discovered was out of date, unfortunately) and bashed and
  115. X    badgered it into a vi "feel-alike".  It retains the multiple
  116. X    buffer/multiple window features of uemacs, but the
  117. X    "finger-feel", if you will, is very much that of vi.  It is
  118. X    definitely not a clone, in that some substantial stuff is
  119. X    missing, and the screen doesn't look quite the same.  But what
  120. X    matters most is that one's "muscle memory" does the right thing
  121. X    to the text in front of you, and that is what vile tries to do
  122. X    for vi users.   THIS IS NOT A "CLONE"!
  123. X
  124. X    This is the first really public version of vile.  It is
  125. X    version three.  Users of previous versions will hopefully find
  126. X    the additions of ":" command line ranges and the ! filter
  127. X    operator helpful. 
  128. X
  129. X    The collective developers of Micro-Emacs should be
  130. X    complimented that the changes were as easy as they were.  The
  131. X    code was pretty clean and well designed before I started on
  132. X    it.  I'm not sure that the same can be said anymore... 
  133. X
  134. X    The benefits over standard vi include:
  135. X        - multiple files open at once
  136. X        - multiple windows on the screen
  137. X        - a larger set of operator commands
  138. X        - the possibility of porting to your favorite micro.
  139. X            (mind you, I haven't even tried this on a small
  140. X                UNIX machine, let alone DOS etc...)
  141. X        - more uniform undo/yank register treatment
  142. X        - using tags doesn't lose your last search pattern
  143. X        - "next error" cursor positioning after compilation
  144. X    Of course, it _may_ lack some of vi's reliability. :-)
  145. X
  146. X    ( Although I can't imagine the emacs folks wanting to buy much
  147. X    of this stuff back (insert mode, anyone? :-), they might
  148. X    want to look at:
  149. X        - full global undo
  150. X        - tags support
  151. X        - better (maybe?) UNIX terminal handling
  152. X        - better UNIX shell escapes
  153. X        - terminal scroll support
  154. X        - multiple yank registers (formerly called kill buffers)
  155. X        - multiple marks  (actually kind of messy)
  156. X        - improved aesthetics of window splitting and deleting
  157. X        - "next error" cursor positioning
  158. X        - list mode )
  159. X
  160. X    Take a look at vile.hlp for more information about features
  161. X    and differences. 
  162. X
  163. X    In general, I suspect that the quality of the code is roughly
  164. X    on a par with MicroEmacs.  I've been using vile regularly under
  165. X    both SunOS and 386 UNIX for about a year, with no major problems
  166. X    (that havn't been fixed).  Another dedicated user has been
  167. X    running it on various flavors of 386 UNIX (Bell, Open DeskTop,
  168. X    Xenix) and Ultrix, also with no problems.
  169. X
  170. X    I have not tried this on a small system, or even _any_
  171. X    non-UNIX system.  I'm sure work will be required to make
  172. X    it work on DOS again, for instance -- especially for spawning
  173. X    sub-shells, etc. 
  174. X
  175. X    I ifdef'ed out the language features (user-defined procs,
  176. X    etc.) a long time ago -- I don't know if they still work,
  177. X    though I didn't actively try to break them. 
  178. X
  179. X    If anyone is interested in doing major work on this thing, let me
  180. X    know -- I have some ideas on how to make a full ex mode work, for 
  181. X    instance, and on how to add the ":map" command.  Also, take a look 
  182. X    at the buglist...
  183. X
  184. X    Hope you enjoy -- 
  185. X
  186. X    Paul G. Fox    June 3, 1991
  187. X    pgf@cayman.com
  188. X
  189. p.s.  The code distributed with vile in the "shortnames" subdirectory
  190. X    is covered by GNU Public License.  The vile code itself in the
  191. X    upper level directory is _not_ covered by the GNU public license. 
  192. X
  193. p.p.s By the way, I'm _not_ the same Paul Fox who wrote Crisp, the Brief
  194. X    work-alike.
  195. SHAR_EOF
  196. chmod 0444 README ||
  197. echo 'restore of README failed'
  198. Wc_c="`wc -c < 'README'`"
  199. test 3835 -eq "$Wc_c" ||
  200.     echo 'README: original size 3835, current size' "$Wc_c"
  201. # ============= ansi.c ==============
  202. echo 'x - extracting ansi.c (Text)'
  203. sed 's/^X//' << 'SHAR_EOF' > 'ansi.c' &&
  204. /*
  205. X * The routines in this file provide support for ANSI style terminals
  206. X * over a serial line. The serial I/O services are provided by routines in
  207. X * "termio.c". It compiles into nothing if not an ANSI device.
  208. X */
  209. X
  210. #define    termdef    1            /* don't define "term" external */
  211. X
  212. #include        <stdio.h>
  213. #include    "estruct.h"
  214. #include        "edef.h"
  215. X
  216. #if     ANSI
  217. X
  218. #if    AMIGA
  219. #define NROW    23                      /* Screen size.                 */
  220. #define NCOL    77                      /* Edit if you want to.         */
  221. #else
  222. #define NROW    24                      /* Screen size.                 */
  223. #define NCOL    80                      /* Edit if you want to.         */
  224. #endif
  225. #define    NPAUSE    100            /* # times thru update to pause */
  226. #define    MARGIN    8            /* size of minimim margin and    */
  227. #define    SCRSIZ    64            /* scroll size for extended lines */
  228. #define BEL     0x07                    /* BEL character.               */
  229. #define ESC     0x1B                    /* ESC character.               */
  230. X
  231. extern  int     ttopen();               /* Forward references.          */
  232. extern  int     ttgetc();
  233. extern  int     ttputc();
  234. extern  int     ttflush();
  235. extern  int     ttclose();
  236. extern  int     ansimove();
  237. extern  int     ansieeol();
  238. extern  int     ansieeop();
  239. extern  int     ansibeep();
  240. extern  int     ansiopen();
  241. extern    int    ansirev();
  242. extern    int    ansiclose();
  243. extern    int    ansikopen();
  244. extern    int    ansikclose();
  245. extern    int    ansicres();
  246. #if SCROLLCODE
  247. extern    int    ansiscroll();
  248. #endif
  249. X
  250. #if    COLOR
  251. extern    int    ansifcol();
  252. extern    int    ansibcol();
  253. X
  254. int    cfcolor = -1;        /* current forground color */
  255. int    cbcolor = -1;        /* current background color */
  256. X
  257. #if    AMIGA
  258. /* apperently the AMIGA does not follow the ANSI standards as
  259. X   regards to colors....maybe because of the default pallette
  260. X   settings?
  261. */
  262. X
  263. int coltran[8] = {2, 3, 5, 7, 0, 4, 6, 1};    /* color translation table */
  264. #endif
  265. #endif
  266. X
  267. /*
  268. X * Standard terminal interface dispatch table. Most of the fields point into
  269. X * "termio" code.
  270. X */
  271. TERM    term    = {
  272. X    NROW-1,
  273. X        NROW-1,
  274. X        NCOL,
  275. X        NCOL,
  276. X    MARGIN,
  277. X    SCRSIZ,
  278. X    NPAUSE,
  279. X        ansiopen,
  280. X        ansiclose,
  281. X    ansikopen,
  282. X    ansikclose,
  283. X        ttgetc,
  284. X        ttputc,
  285. X        ttflush,
  286. X        ansimove,
  287. X        ansieeol,
  288. X        ansieeop,
  289. X        ansibeep,
  290. X    ansirev,
  291. X    ansicres
  292. #if    COLOR
  293. X    , ansifcol,
  294. X    ansibcol
  295. #endif
  296. #if SCROLLCODE
  297. X    , ansiscroll
  298. #endif
  299. };
  300. X
  301. csi()
  302. {
  303. X    ttputc(ESC);
  304. X    ttputc('[');
  305. }
  306. X
  307. #if    COLOR
  308. ansifcol(color)        /* set the current output color */
  309. X
  310. int color;    /* color to set */
  311. X
  312. {
  313. X    if (color == cfcolor)
  314. X        return;
  315. X    csi();
  316. #if    AMIGA
  317. X    ansiparm(coltran[color]+30);
  318. #else
  319. X    ansiparm(color+30);
  320. #endif
  321. X    ttputc('m');
  322. X    cfcolor = color;
  323. }
  324. X
  325. ansibcol(color)        /* set the current background color */
  326. X
  327. int color;    /* color to set */
  328. X
  329. {
  330. X    if (color == cbcolor)
  331. X        return;
  332. X    csi();
  333. #if    AMIGA
  334. X    ansiparm(coltran[color]+40);
  335. #else
  336. X    ansiparm(color+40);
  337. #endif
  338. X    ttputc('m');
  339. X        cbcolor = color;
  340. }
  341. #endif
  342. X
  343. ansimove(row, col)
  344. {
  345. X    csi();
  346. X        if (row) ansiparm(row+1);
  347. X        ttputc(';');
  348. X        if (col) ansiparm(col+1);
  349. X        ttputc('H');
  350. }
  351. X
  352. ansieeol()
  353. {
  354. X    csi();
  355. X        ttputc('K');
  356. }
  357. X
  358. ansieeop()
  359. {
  360. #if    COLOR
  361. X    ansifcol(gfcolor);
  362. X    ansibcol(gbcolor);
  363. #endif
  364. X    csi();
  365. X        ttputc('J');
  366. }
  367. X
  368. X
  369. ansirev(state)        /* change reverse video state */
  370. X
  371. int state;    /* TRUE = reverse, FALSE = normal */
  372. X
  373. {
  374. #if    COLOR
  375. X    int ftmp, btmp;        /* temporaries for colors */
  376. #else
  377. X    static int revstate = -1;
  378. X    if (state == revstate)
  379. X        return;
  380. X    revstate = state;
  381. #endif
  382. X
  383. X    csi();
  384. X    if (state) ttputc('7');
  385. X    ttputc('m');
  386. #if    COLOR
  387. X    if (state == FALSE) {
  388. X        ftmp = cfcolor;
  389. X        btmp = cbcolor;
  390. X        cfcolor = -1;
  391. X        cbcolor = -1;
  392. X        ansifcol(ftmp);
  393. X        ansibcol(btmp);
  394. X    }
  395. #endif
  396. }
  397. X
  398. ansicres()    /* change screen resolution */
  399. {
  400. X    return(TRUE);
  401. }
  402. X
  403. spal(dummy)        /* change pallette settings */
  404. {
  405. X    /* none for now */
  406. }
  407. X
  408. ansibeep()
  409. {
  410. X        ttputc(BEL);
  411. X        ttflush();
  412. }
  413. X
  414. #if SCROLLCODE
  415. X
  416. /* if your ansi terminal can scroll regions, like the vt100, then define
  417. X    SCROLL_REG.  If not, you can use delete/insert line code, which
  418. X    is prettier but slower if you do it a line at a time instead of
  419. X    all at once.
  420. */
  421. X
  422. #define SCROLL_REG 1
  423. X
  424. /* move howmany lines starting at from to to */
  425. ansiscroll(from,to,howmany)
  426. {
  427. X    int i;
  428. X    if (to == from) return;
  429. #if SCROLL_REG
  430. X    if (to < from) {
  431. X        ansiscrollregion(to, from + howmany - 1);
  432. X        ansimove(from + howmany - 1,0);
  433. X        for (i = from - to; i > 0; i--)
  434. X            ttputc('\n');
  435. X    } else { /* from < to */
  436. X        ansiscrollregion(from, to + howmany - 1);
  437. X        ansimove(from);
  438. X        for (i = to - from; i > 0; i--) {
  439. X            ttputc(ESC);
  440. X            ttputc('M');
  441. X        }
  442. X    }
  443. X    ansiscrollregion(0, term.t_mrow);
  444. X        
  445. #else /* use insert and delete line */
  446. #if PRETTIER_SCROLL
  447. X    if (abs(from-to) > 1) {
  448. X        ansiscroll(from, (from<to) ? to-1:to+1, howmany);
  449. X        if (from < to)
  450. X            from = to-1;
  451. X        else
  452. X            from = to+1;    
  453. X    }
  454. #endif
  455. X    if (to < from) {
  456. X        ansimove(to,0);
  457. X        csi();
  458. X        if (from - to > 1) ansiparm(from - to);
  459. X        ttputc('M'); /* delete */
  460. X        ansimove(to+howmany,0);
  461. X        csi();
  462. X        if (from - to > 1) ansiparm(from - to);
  463. X        ttputc('L'); /* insert */
  464. X    } else {
  465. X        ansimove(from+howmany,0);
  466. X        csi();
  467. X        if (to - from > 1) ansiparm(to - from);
  468. X        ttputc('M'); /* delete */
  469. X        ansimove(from,0);
  470. X        csi();
  471. X        if (to - from > 1) ansiparm(to - from);
  472. X        ttputc('L'); /* insert */
  473. X    }
  474. #endif
  475. }
  476. X
  477. #if SCROLL_REG
  478. ansiscrollregion(top,bot)
  479. {
  480. X    csi();
  481. X    if (top) ansiparm(top + 1);
  482. X    ttputc(';');
  483. X    if (bot != term.t_nrow) ansiparm(bot + 1);
  484. X    ttputc('r');
  485. }
  486. #endif
  487. X
  488. #endif
  489. X
  490. ansiparm(n)
  491. register int    n;
  492. {
  493. X        register int q,r;
  494. X
  495. X        q = n/10;
  496. X        if (q != 0) {
  497. X        r = q/10;
  498. X        if (r != 0) {
  499. X            ttputc((r%10)+'0');
  500. X        }
  501. X        ttputc((q%10) + '0');
  502. X        }
  503. X        ttputc((n%10) + '0');
  504. }
  505. X
  506. ansiopen()
  507. {
  508. #if     V7 | USG | BSD
  509. #if 0
  510. X        register char *cp;
  511. X        char *getenv();
  512. X
  513. X        if ((cp = getenv("TERM")) == NULL) {
  514. X                puts("Shell variable TERM not defined!");
  515. X                exit(1);
  516. X        }
  517. X        if (strcmp(cp, "vt100") != 0 && strcmp(cp, "ansi") != 0) {
  518. X                puts("Terminal type not 'vt100' or 'ansi'!");
  519. X                exit(1);
  520. X        }
  521. #endif
  522. #endif
  523. X    strcpy(sres, "NORMAL");
  524. X    revexist = TRUE;
  525. X        ttopen();
  526. }
  527. X
  528. ansiclose()
  529. {
  530. #if    COLOR
  531. X    ansifcol(7);
  532. X    ansibcol(0);
  533. #endif
  534. X    ttclose();
  535. }
  536. X
  537. ansikopen()    /* open the keyboard (a noop here) */
  538. {
  539. }
  540. X
  541. ansikclose()    /* close the keyboard (a noop here) */
  542. {
  543. }
  544. X
  545. #if    FLABEL
  546. fnclabel(f, n)        /* label a function key */
  547. int f,n;    /* default flag, numeric argument [unused] */
  548. {
  549. X    /* on machines with no function keys...don't bother */
  550. X    return(TRUE);
  551. }
  552. #endif
  553. #else
  554. ansihello()
  555. {
  556. }
  557. #endif
  558. SHAR_EOF
  559. chmod 0444 ansi.c ||
  560. echo 'restore of ansi.c failed'
  561. Wc_c="`wc -c < 'ansi.c'`"
  562. test 6488 -eq "$Wc_c" ||
  563.     echo 'ansi.c: original size 6488, current size' "$Wc_c"
  564. # ============= at386.c ==============
  565. echo 'x - extracting at386.c (Text)'
  566. sed 's/^X//' << 'SHAR_EOF' > 'at386.c' &&
  567. /*    AT386:   hacked tcap.c for the 386 console, when you don't
  568. X        have libtermcap.   grrr.
  569. */
  570. X
  571. #define    termdef    1            /* don't define "term" external */
  572. X
  573. #include <stdio.h>
  574. #include    "estruct.h"
  575. #include        "edef.h"
  576. X
  577. #if AT386
  578. X
  579. #define NROW    25                      /* Screen size.                 */
  580. #define NCOL    80                      /* Edit if you want to.         */
  581. #define    MARGIN    8
  582. #define    SCRSIZ    64
  583. #define    NPAUSE    10            /* # times thru update to pause */
  584. #define BEL     0x07
  585. #define ESC     0x1B
  586. X
  587. extern int      ttopen();
  588. extern int      ttgetc();
  589. extern int      ttputc();
  590. extern int    tgetnum();
  591. extern int      ttflush();
  592. extern int      ttclose();
  593. extern int    at386kopen();
  594. extern int    at386kclose();
  595. extern int      at386move();
  596. extern int      at386eeol();
  597. extern int      at386eeop();
  598. extern int      at386beep();
  599. extern int    at386rev();
  600. extern int    at386cres();
  601. extern int      at386open();
  602. extern int      tput();
  603. extern char     *tgoto();
  604. #if    COLOR
  605. extern    int    at386fcol();
  606. extern    int    at386bcol();
  607. #endif
  608. #if    SCROLLCODE
  609. extern    int    at386scroll_delins();
  610. #endif
  611. X
  612. #define TCAPSLEN 315
  613. char at386buf[TCAPSLEN];
  614. char *UP, PC, *CM, *CE, *CL, *SO, *SE;
  615. X
  616. #if    SCROLLCODE
  617. char *DL, *AL, *SF, *SR;
  618. #endif
  619. X
  620. TERM term = {
  621. X    NROW-1,
  622. X    NROW-1,
  623. X    NCOL,
  624. X    NCOL,
  625. X    MARGIN,
  626. X    SCRSIZ,
  627. X    NPAUSE,
  628. X        at386open,
  629. X        ttclose,
  630. X        at386kopen,
  631. X        at386kclose,
  632. X        ttgetc,
  633. X        ttputc,
  634. X        ttflush,
  635. X        at386move,
  636. X        at386eeol,
  637. X        at386eeop,
  638. X        at386beep,
  639. X        at386rev,
  640. X        at386cres
  641. #if    COLOR
  642. X    , at386fcol,
  643. X    at386bcol
  644. #endif
  645. #if    SCROLLCODE
  646. X    , NULL        /* set dynamically at open time */
  647. #endif
  648. };
  649. X
  650. at386open()
  651. {
  652. X        char *getenv();
  653. X        char *t, *p, *tgetstr();
  654. X        char tcbuf[1024];
  655. X        char *tv_stype;
  656. X        char err_str[72];
  657. X
  658. X        CL = "\033[2J\033[H";
  659. X        CE = "\033[K";
  660. X        UP = "\033[A";
  661. X    SE = "\033[m";
  662. X    SO = "\033[7m";
  663. X    revexist = TRUE;
  664. X
  665. X
  666. #if SCROLLCODE
  667. X    DL = "\033[1M";
  668. X    AL = "\033[1L";
  669. X    term.t_scroll = at386scroll_delins;
  670. #endif
  671. X        ttopen();
  672. }
  673. X
  674. at386kopen()
  675. {
  676. X    strcpy(sres, "NORMAL");
  677. }
  678. X
  679. at386kclose()
  680. {
  681. }
  682. X
  683. csi()
  684. {
  685. X    ttputc(ESC);
  686. X    ttputc('[');
  687. }
  688. X
  689. ansiparm(n)
  690. register int    n;
  691. {
  692. X        register int q,r;
  693. X
  694. X        q = n/10;
  695. X        if (q != 0) {
  696. X        r = q/10;
  697. X        if (r != 0) {
  698. X            ttputc((r%10)+'0');
  699. X        }
  700. X        ttputc((q%10) + '0');
  701. X        }
  702. X        ttputc((n%10) + '0');
  703. }
  704. X
  705. at386move(row, col)
  706. register int row, col;
  707. {
  708. X    csi();
  709. X        if (row) ansiparm(row+1);
  710. X        ttputc(';');
  711. X        if (col) ansiparm(col+1);
  712. X        ttputc('H');
  713. }
  714. X
  715. at386eeol()
  716. {
  717. X        fputs(CE,stdout);
  718. }
  719. X
  720. at386eeop()
  721. {
  722. X        fputs(CL,stdout);
  723. }
  724. X
  725. at386rev(state)        /* change reverse video status */
  726. int state;        /* FALSE = normal video, TRUE = reverse video */
  727. {
  728. X    static int revstate = -1;
  729. X    if (state == revstate)
  730. X        return;
  731. X    revstate = state;
  732. X    if (state) {
  733. X        if (SO != NULL)
  734. X            fputs(SO,stdout);
  735. X    } else {
  736. X        if (SE != NULL)
  737. X            fputs(SE,stdout);
  738. X    }
  739. }
  740. X
  741. at386cres()    /* change screen resolution */
  742. {
  743. X    return(TRUE);
  744. }
  745. X
  746. #if SCROLLCODE
  747. X
  748. /* 
  749. PRETTIER_SCROLL is prettier but slower -- it scrolls 
  750. X        a line at a time instead of all at once.
  751. */
  752. X
  753. /* move howmany lines starting at from to to */
  754. at386scroll_delins(from,to,howmany)
  755. {
  756. X    int i;
  757. X    if (to == from) return;
  758. #if PRETTIER_SCROLL
  759. X    if (abs(from-to) > 1) {
  760. X        at386scroll_delins(from, (from<to) ? to-1:to+1, howmany);
  761. X        if (from < to)
  762. X            from = to-1;
  763. X        else
  764. X            from = to+1;    
  765. X    }
  766. #endif
  767. X    if (to < from) {
  768. X        at386move(to,0);
  769. X        for (i = from - to; i > 0; i--)
  770. X            fputs(DL,stdout);
  771. X        at386move(to+howmany,0);
  772. X        for (i = from - to; i > 0; i--)
  773. X            fputs(AL,stdout);
  774. X    } else {
  775. X        at386move(from+howmany,0);
  776. X        for (i = to - from; i > 0; i--)
  777. X            fputs(DL,stdout);
  778. X        at386move(from,0);
  779. X        for (i = to - from; i > 0; i--)
  780. X            fputs(AL,stdout);
  781. X    }
  782. }
  783. X
  784. #endif
  785. X
  786. spal(dummy)    /* change palette string */
  787. {
  788. X    /*    Does nothing here    */
  789. }
  790. X
  791. X
  792. #if    COLOR
  793. at386fcol()    /* no colors here, ignore this */
  794. {
  795. }
  796. X
  797. at386bcol()    /* no colors here, ignore this */
  798. {
  799. }
  800. #endif
  801. X
  802. at386beep()
  803. {
  804. X    ttputc(BEL);
  805. }
  806. X
  807. X
  808. #if    FLABEL
  809. fnclabel(f, n)        /* label a function key */
  810. int f,n;    /* default flag, numeric argument [unused] */
  811. {
  812. X    /* on machines with no function keys...don't bother */
  813. X    return(TRUE);
  814. }
  815. #endif
  816. #else
  817. X
  818. hello()
  819. {
  820. }
  821. X
  822. #endif
  823. SHAR_EOF
  824. chmod 0444 at386.c ||
  825. echo 'restore of at386.c failed'
  826. Wc_c="`wc -c < 'at386.c'`"
  827. test 4175 -eq "$Wc_c" ||
  828.     echo 'at386.c: original size 4175, current size' "$Wc_c"
  829. # ============= basic.c ==============
  830. echo 'x - extracting basic.c (Text)'
  831. sed 's/^X//' << 'SHAR_EOF' > 'basic.c' &&
  832. /*
  833. X * The routines in this file move the cursor around on the screen. They
  834. X * compute a new value for the cursor, then adjust ".". The display code
  835. X * always updates the cursor location, so only moves between lines, or
  836. X * functions that adjust the top line in the window and invalidate the
  837. X * framing, are hard.
  838. X */
  839. #include        <stdio.h>
  840. #include    "estruct.h"
  841. #include        "edef.h"
  842. X
  843. /*
  844. X * Move the cursor to the
  845. X * beginning of the current line.
  846. X * Trivial.
  847. X */
  848. gotobol(f, n)
  849. {
  850. X        curwp->w_doto  = 0;
  851. X        return (TRUE);
  852. }
  853. X
  854. /*
  855. X * Move the cursor backwards by "n" characters. If "n" is less than zero call
  856. X * "forwchar" to actually do the move. Otherwise compute the new cursor
  857. X * location. Error if you try and move out of the buffer. Set the flag if the
  858. X * line pointer for dot changes.
  859. X */
  860. backchar(f, n)
  861. register int    n;
  862. {
  863. X        register LINE   *lp;
  864. X
  865. X    if (f == FALSE) n = 1;
  866. X        if (n < 0)
  867. X                return (forwchar(f, -n));
  868. X        while (n--) {
  869. X                if (curwp->w_doto == 0) {
  870. X                        if ((lp=lback(curwp->w_dotp)) == curbp->b_linep)
  871. X                                return (FALSE);
  872. X                        curwp->w_dotp  = lp;
  873. X                        curwp->w_doto  = llength(lp);
  874. X                        curwp->w_flag |= WFMOVE;
  875. X                } else
  876. X                        curwp->w_doto--;
  877. X        }
  878. X        return (TRUE);
  879. }
  880. X
  881. /*
  882. X * Move the cursor to the end of the current line. Trivial. No errors.
  883. X */
  884. gotoeol(f, n)
  885. {
  886. X    if (f == TRUE) {
  887. X        if (n > 0)
  888. X             --n;
  889. X        else if (n < 0)
  890. X             ++n;
  891. X        forwline(f,n);
  892. X    }
  893. X        curwp->w_doto  = llength(curwp->w_dotp);
  894. X    curgoal = HUGE;
  895. X        return (TRUE);
  896. }
  897. X
  898. /*
  899. X * Move the cursor forwards by "n" characters. If "n" is less than zero call
  900. X * "backchar" to actually do the move. Otherwise compute the new cursor
  901. X * location, and move ".". Error if you try and move off the end of the
  902. X * buffer. Set the flag if the line pointer for dot changes.
  903. X */
  904. forwchar(f, n)
  905. register int    n;
  906. {
  907. X    if (f == FALSE) n = 1;
  908. X        if (n < 0)
  909. X                return (backchar(f, -n));
  910. X        while (n--) {
  911. X                if (curwp->w_doto == llength(curwp->w_dotp)) {
  912. X                        if (curwp->w_dotp == curbp->b_linep ||
  913. X                    lforw(curwp->w_dotp) == curbp->b_linep)
  914. X                                return (FALSE);
  915. X                        curwp->w_dotp  = lforw(curwp->w_dotp);
  916. X                        curwp->w_doto  = 0;
  917. X                        curwp->w_flag |= WFMOVE;
  918. X                } else
  919. X                        curwp->w_doto++;
  920. X        }
  921. X        return (TRUE);
  922. }
  923. X
  924. gotoline(f, n)        /* move to a particular line.
  925. X               argument (n) must be a positive integer for
  926. X               this to actually do anything        */
  927. {
  928. X    register int status;    /* status return */
  929. X
  930. X    /* get an argument if one doesnt exist */
  931. X    if (f == FALSE) {
  932. X        return(gotoeob(f,n));
  933. X    }
  934. X
  935. X    if (n < 1)        /* if a bogus argument...then leave */
  936. X        return(FALSE);
  937. X
  938. X    /* first, we go to the start of the buffer */
  939. X        curwp->w_dotp  = lforw(curbp->b_linep);
  940. X        curwp->w_doto  = 0;
  941. X    status = forwline(f, n-1);
  942. X    if (status == TRUE)
  943. X        firstnonwhite(f,n);
  944. X    return(status);
  945. }
  946. X
  947. /*
  948. X * Goto the beginning of the buffer. Massive adjustment of dot. This is
  949. X * considered to be hard motion; it really isn't if the original value of dot
  950. X * is the same as the new value of dot.
  951. X */
  952. gotobob(f, n)
  953. {
  954. X        curwp->w_dotp  = lforw(curbp->b_linep);
  955. X        curwp->w_doto  = 0;
  956. X        curwp->w_flag |= WFMOVE;
  957. X        return (TRUE);
  958. }
  959. X
  960. /*
  961. X * Move to the end of the buffer. Dot is always put at the end of the file
  962. X * (ZJ). The standard screen code does most of the hard parts of update.
  963. X */
  964. gotoeob(f, n)
  965. {
  966. X        curwp->w_dotp  = lback(curbp->b_linep);
  967. X    firstnonwhite(FALSE,1);
  968. X        curwp->w_flag |= WFMOVE;
  969. X        return (TRUE);
  970. }
  971. X
  972. gotobos(f,n)
  973. {
  974. X    int s = TRUE;
  975. X    if (f == FALSE || n <= 0) n = 1;
  976. X    curwp->w_dotp = curwp->w_linep;
  977. X    while (--n) {
  978. X        if ((s = forwline(FALSE,1)) != TRUE)
  979. X            break;
  980. X    }
  981. X    firstnonwhite(f,n);
  982. X    return (s);
  983. }
  984. X
  985. gotomos(f,n)
  986. {
  987. X    return gotobos(TRUE,curwp->w_ntrows/2);
  988. }
  989. X
  990. gotoeos(f,n)
  991. {
  992. X    return gotobos(TRUE,curwp->w_ntrows-(f==TRUE? n-1:0));
  993. }
  994. X
  995. /*
  996. X * Move forward by full lines. If the number of lines to move is less than
  997. X * zero, call the backward line function to actually do it. The last command
  998. X * controls how the goal column is set. No errors are
  999. X * possible.
  1000. X */
  1001. forwline(f, n)
  1002. {
  1003. X        register LINE   *dlp;
  1004. X
  1005. X    if (f == FALSE) n = 1;
  1006. X        if (n < 0)
  1007. X                return (backline(f, -n));
  1008. X
  1009. X    /* if we are on the last line as we start....fail the command */
  1010. X    if (curwp->w_dotp == curbp->b_linep)
  1011. X        return(FALSE);
  1012. X
  1013. X    /* if the last command was not a line move,
  1014. X       reset the goal column */
  1015. X        if (curgoal < 0)
  1016. X                curgoal = getccol(FALSE);
  1017. X
  1018. X    /* and move the point down */
  1019. X        dlp = curwp->w_dotp;
  1020. X        while (n-- && dlp!=curbp->b_linep)
  1021. X                dlp = lforw(dlp);
  1022. X
  1023. X    /* resetting the current position */
  1024. X        curwp->w_dotp  = (dlp == curbp->b_linep) ? lback(dlp) : dlp;
  1025. X        curwp->w_doto  = getgoal(dlp);
  1026. X        curwp->w_flag |= WFMOVE;
  1027. X        return (TRUE);
  1028. }
  1029. X
  1030. firstnonwhite(f,n)
  1031. {
  1032. X    int c;
  1033. X        curwp->w_doto  = 0;
  1034. X    while ( curwp->w_doto != llength(curwp->w_dotp) && 
  1035. X            isspace(lgetc(curwp->w_dotp, curwp->w_doto)) )
  1036. X        curwp->w_doto++;
  1037. X    return (TRUE);
  1038. }
  1039. X
  1040. lastnonwhite(f,n)
  1041. {
  1042. X    int c;
  1043. X        curwp->w_doto  = llength(curwp->w_dotp)-1;
  1044. X    while ( curwp->w_doto != 0 && 
  1045. X        ((c = lgetc(curwp->w_dotp, curwp->w_doto)) == ' ' || c == '\t'))
  1046. X        curwp->w_doto--;
  1047. X    return (TRUE);
  1048. X
  1049. }
  1050. X
  1051. /* like forwline, but got to first non-white char position */
  1052. forwbline(f,n)
  1053. {
  1054. X    int s;
  1055. X
  1056. X    if (f == FALSE) n = 1;
  1057. X    if ((s = forwline(f,n)) != TRUE)
  1058. X        return (s);
  1059. X    firstnonwhite(f,n);
  1060. X    return(TRUE);
  1061. }
  1062. X
  1063. /* like backline, but got to first non-white char position */
  1064. backbline(f,n)
  1065. {
  1066. X    int s;
  1067. X
  1068. X    if (f == FALSE) n = 1;
  1069. X    if ((s = backline(f,n)) != TRUE)
  1070. X        return (s);
  1071. X    firstnonwhite(f,n);
  1072. X    return(TRUE);
  1073. }
  1074. X
  1075. /*
  1076. X * This function is like "forwline", but goes backwards. The scheme is exactly
  1077. X * the same. Check for arguments that are less than zero and call your
  1078. X * alternate. Figure out the new line and call "movedot" to perform the
  1079. X * motion. No errors are possible.
  1080. X */
  1081. backline(f, n)
  1082. {
  1083. X        register LINE   *dlp;
  1084. X
  1085. X    if (f == FALSE) n = 1;
  1086. X        if (n < 0)
  1087. X                return (forwline(f, -n));
  1088. X
  1089. X
  1090. X    /* if we are on the last line as we start....fail the command */
  1091. X    if (lback(curwp->w_dotp) == curbp->b_linep)
  1092. X        return(FALSE);
  1093. X
  1094. X    /* if the last command was not note a line move,
  1095. X       reset the goal column */
  1096. X        if (curgoal < 0)
  1097. X                curgoal = getccol(FALSE);
  1098. X
  1099. X    /* and move the point up */
  1100. X        dlp = curwp->w_dotp;
  1101. X        while (n-- && lback(dlp)!=curbp->b_linep)
  1102. X                dlp = lback(dlp);
  1103. X
  1104. X    /* reseting the current position */
  1105. X        curwp->w_dotp  = dlp;
  1106. X        curwp->w_doto  = getgoal(dlp);
  1107. X        curwp->w_flag |= WFMOVE;
  1108. X        return (TRUE);
  1109. }
  1110. X
  1111. #if    WORDPRO
  1112. X
  1113. gotobop(f,n)
  1114. {
  1115. X    return(backlinebeg(f,n,"\n.","ILPQb"));
  1116. }
  1117. gotoeop(f,n)
  1118. {
  1119. X    return(forwlinebeg(f,n,"\n.","ILPQb"));
  1120. }
  1121. gotobosec(f,n)
  1122. {
  1123. #if STUTTER_SEC_CMD
  1124. X    int this1key;
  1125. X    if (!clexec) {
  1126. X        this1key = last1key;
  1127. X        kbd_seq();
  1128. X        if (this1key != last1key) {
  1129. X            TTbeep();
  1130. X            return(FALSE);
  1131. X        }
  1132. X    }
  1133. #endif
  1134. X    return(backlinebeg(f,n,"{\f.","SHN"));
  1135. }
  1136. gotoeosec(f,n)
  1137. {
  1138. #if STUTTER_SEC_CMD
  1139. X    int this1key;
  1140. X    if (!clexec) {
  1141. X        this1key = last1key;
  1142. X        kbd_seq();
  1143. X        if (this1key != last1key) {
  1144. X            TTbeep();
  1145. X            return(FALSE);
  1146. X        }
  1147. X    }
  1148. #endif
  1149. X    return(forwlinebeg(f,n,"{\f.","SHN"));
  1150. }
  1151. X
  1152. backlinebeg(f, n, s1, s2)
  1153. char *s1, *s2;
  1154. {
  1155. X    register int suc;    /* success of last backchar */
  1156. X    LINE *odotp;
  1157. X
  1158. X    if (f == FALSE) n = 1;
  1159. X    if (n < 0)    /* the other way...*/
  1160. X        return(gotoeop(f, -n));
  1161. X
  1162. X    odotp = curwp->w_dotp;
  1163. X    while (n-- > 0) {    /* for each one asked for */
  1164. X
  1165. X        /* first scan back until we are in a word */
  1166. X        suc = backchar(FALSE, 1);
  1167. X        while (!inword() && suc)
  1168. X            suc = backchar(FALSE, 1);
  1169. X
  1170. X        while (lback(curwp->w_dotp) != curbp->b_linep) {
  1171. X            if (issecbeg(s1,s2) == TRUE)
  1172. X                break;
  1173. X            curwp->w_dotp = lback(curwp->w_dotp);
  1174. X        }
  1175. X    }
  1176. X    /* if doing an operation and we moved */
  1177. X    if (doingopcmd && odotp != curwp->w_dotp) {
  1178. X        curwp->w_dotp = lforw(curwp->w_dotp);
  1179. X        curwp->w_doto = 0;
  1180. X    } else {
  1181. X        firstnonwhite(f,n);
  1182. X    }
  1183. X    curwp->w_flag |= WFMOVE;    /* force screen update */
  1184. X    return(TRUE);
  1185. }
  1186. X
  1187. forwlinebeg(f, n, s1, s2)
  1188. char *s1, *s2;
  1189. {
  1190. X    register int suc;    /* success of last backchar */
  1191. X    LINE *odotp;
  1192. X
  1193. X    if (f == FALSE) n = 1;
  1194. X    if (n < 0)    /* the other way...*/
  1195. X        return(gotobop(f, -n));
  1196. X
  1197. X    odotp = curwp->w_dotp;
  1198. X    while (n-- > 0) {    /* for each one asked for */
  1199. X
  1200. X        /* first scan forward until we are in a word */
  1201. X        suc = forwchar(FALSE, 1);
  1202. X        while (!inword() && suc)
  1203. X            suc = forwchar(FALSE, 1);
  1204. X        curwp->w_doto = 0;    /* and go to the B-O-Line */
  1205. X        if (suc)    /* of next line if not at EOF */
  1206. X            curwp->w_dotp = lforw(curwp->w_dotp);
  1207. X
  1208. X        while (curwp->w_dotp != curbp->b_linep) {
  1209. X            if (issecbeg(s1,s2) == TRUE)
  1210. X                break;
  1211. X            curwp->w_dotp = lforw(curwp->w_dotp);
  1212. X        }
  1213. X    }
  1214. X    /* if doing an operation and we moved */
  1215. X    if (doingopcmd && odotp != curwp->w_dotp) {
  1216. X        curwp->w_dotp = lback(curwp->w_dotp);
  1217. X        curwp->w_doto = llength(curwp->w_dotp)-1;
  1218. X    } else {
  1219. X        firstnonwhite(f,n);
  1220. X    }
  1221. X    curwp->w_flag |= WFMOVE;    /* force screen update */
  1222. X    return(TRUE);
  1223. }
  1224. X
  1225. /* a new "section" of some sort starts at the beginning of the line,
  1226. X    with either a character from s1 or a "." followed by a character
  1227. X    from s2 */
  1228. issecbeg(s1,s2)
  1229. char *s1,*s2;
  1230. {
  1231. X    register char *cp1, *cp2;
  1232. X    register int l, c1, c2;
  1233. X
  1234. X    l = llength(curwp->w_dotp);
  1235. X    for(cp1 = s1; *cp1 != 0; cp1++) {
  1236. X        if ( l == 0) {
  1237. X            if (*cp1 == '\n')
  1238. X                return TRUE;
  1239. X            else
  1240. X                continue;
  1241. X        }
  1242. X        c1 = lgetc(curwp->w_dotp, 0);
  1243. X        if (c1 == '.' && *cp1 == '.' && s2) {
  1244. X            for(cp2 = s2; *cp2 != 0; cp2++) {
  1245. X                if ( l <= 1) {
  1246. X                    if (*cp2 == '\n')
  1247. X                        return TRUE;
  1248. X                    else
  1249. X                        continue;
  1250. X                } 
  1251. X                c2 = lgetc(curwp->w_dotp, 1);
  1252. X                if ( *cp2 == c2 )
  1253. X                    return TRUE;
  1254. X            }
  1255. X            
  1256. X        } else if ( *cp1 == c1 ) {
  1257. X            return TRUE;
  1258. X        }
  1259. X    }
  1260. X    return FALSE;
  1261. }
  1262. #endif
  1263. X
  1264. /*
  1265. X * This routine, given a pointer to a LINE, and the current cursor goal
  1266. X * column, return the best choice for the offset. The offset is returned.
  1267. X * Used by "C-N" and "C-P".
  1268. X */
  1269. getgoal(dlp)
  1270. register LINE   *dlp;
  1271. {
  1272. X        register int    c;
  1273. X        register int    col;
  1274. X        register int    newcol;
  1275. X        register int    dbo;
  1276. X
  1277. X        col = 0;
  1278. X        dbo = 0;
  1279. X        while (dbo != llength(dlp)) {
  1280. X                c = lgetc(dlp, dbo);
  1281. X                newcol = col;
  1282. X        if (((curwp->w_bufp->b_mode&MDLIST) == 0) && c == '\t')
  1283. X                        newcol |= TABMASK;
  1284. X                else if (!isprint(c))
  1285. X                        ++newcol;
  1286. X                ++newcol;
  1287. X                if (newcol > curgoal)
  1288. X                        break;
  1289. X                col = newcol;
  1290. X                ++dbo;
  1291. X        }
  1292. X        return (dbo);
  1293. }
  1294. X
  1295. /*
  1296. X * Scroll forward by a specified number of lines, or by a full page if no
  1297. X * argument.  The "2" in the arithmetic on the window size is
  1298. X * the overlap; this value is the default overlap value in ITS EMACS. Because
  1299. X * this zaps the top line in the display window, we have to do a hard update.
  1300. X */
  1301. forwpage(f, n)
  1302. register int    n;
  1303. {
  1304. X        register LINE   *lp;
  1305. X
  1306. X        if (f == FALSE) {
  1307. X                n = curwp->w_ntrows - 2;        /* Default scroll.      */
  1308. X                if (n <= 0)                     /* Forget the overlap   */
  1309. X                        n = 1;                  /* if tiny window.      */
  1310. X        } else if (n < 0)
  1311. X                return (backpage(f, -n));
  1312. #if     CVMVAS
  1313. X        else                                    /* Convert from pages   */
  1314. X                n *= curwp->w_ntrows;           /* to lines.            */
  1315. #endif
  1316. X        lp = curwp->w_linep;
  1317. X        while (n-- && lp!=curbp->b_linep)
  1318. X                lp = lforw(lp);
  1319. X        curwp->w_linep = lp;
  1320. X        curwp->w_dotp  = lp;
  1321. X        curwp->w_doto  = 0;
  1322. X        curwp->w_flag |= WFHARD;
  1323. X        return (TRUE);
  1324. }
  1325. X
  1326. /*
  1327. X * This command is like "forwpage", but it goes backwards. The "2", like
  1328. X * above, is the overlap between the two windows. The value is from the ITS
  1329. X * EMACS manual. We do a hard update for exactly the same
  1330. X * reason.
  1331. X */
  1332. backpage(f, n)
  1333. register int    n;
  1334. {
  1335. X        register LINE   *lp;
  1336. X
  1337. X        if (f == FALSE) {
  1338. X                n = curwp->w_ntrows - 2;        /* Default scroll.      */
  1339. X                if (n <= 0)                     /* Don't blow up if the */
  1340. X                        n = 1;                  /* window is tiny.      */
  1341. X        } else if (n < 0)
  1342. X                return (forwpage(f, -n));
  1343. #if     CVMVAS
  1344. X        else                                    /* Convert from pages   */
  1345. X                n *= curwp->w_ntrows;           /* to lines.            */
  1346. #endif
  1347. X        lp = curwp->w_linep;
  1348. X        while (n-- && lback(lp)!=curbp->b_linep)
  1349. X                lp = lback(lp);
  1350. X        curwp->w_linep = lp;
  1351. X        curwp->w_dotp  = lp;
  1352. X        curwp->w_doto  = 0;
  1353. X        curwp->w_flag |= WFHARD;
  1354. X        return (TRUE);
  1355. }
  1356. X
  1357. /*
  1358. X * Scroll forward by a specified number of lines, or by a full page if no
  1359. X * argument. The "2" in the arithmetic on the window size is
  1360. X * the overlap; this value is the default overlap value in ITS EMACS. Because
  1361. X * this zaps the top line in the display window, we have to do a hard update.
  1362. X */
  1363. forwhpage(f, n)
  1364. register int    n;
  1365. {
  1366. X        register LINE   *llp, *dlp;
  1367. X
  1368. X        if (f == FALSE) {
  1369. X                n = curwp->w_ntrows / 2;        /* Default scroll.      */
  1370. X                if (n <= 0)                     /* Forget the overlap   */
  1371. X                        n = 1;                  /* if tiny window.      */
  1372. X        } else if (n < 0)
  1373. X                return (backhpage(f, -n));
  1374. #if     CVMVAS
  1375. X        else                                    /* Convert from pages   */
  1376. X                n *= curwp->w_ntrows/2;           /* to lines.            */
  1377. #endif
  1378. X        llp = curwp->w_linep;
  1379. X        dlp = curwp->w_dotp;
  1380. X        while (n-- && lforw(dlp) != curbp->b_linep) {
  1381. X                llp = lforw(llp);
  1382. X                dlp = lforw(dlp);
  1383. X    }
  1384. X        curwp->w_linep = llp;
  1385. X        curwp->w_dotp  = dlp;
  1386. X    firstnonwhite(f,n);
  1387. X        curwp->w_flag |= WFHARD|WFKILLS;
  1388. X        return (TRUE);
  1389. }
  1390. X
  1391. /*
  1392. X * This command is like "forwpage", but it goes backwards. The "2", like
  1393. X * above, is the overlap between the two windows. The value is from the ITS
  1394. X * EMACS manual. We do a hard update for exactly the same
  1395. X * reason.
  1396. X */
  1397. backhpage(f, n)
  1398. register int    n;
  1399. {
  1400. X        register LINE   *llp, *dlp;
  1401. X
  1402. X        if (f == FALSE) {
  1403. X                n = curwp->w_ntrows / 2;        /* Default scroll.      */
  1404. X                if (n <= 0)                     /* Don't blow up if the */
  1405. X                        n = 1;                  /* window is tiny.      */
  1406. X        } else if (n < 0)
  1407. X                return (forwhpage(f, -n));
  1408. #if     CVMVAS
  1409. X        else                                    /* Convert from pages   */
  1410. X                n *= curwp->w_ntrows/2;           /* to lines.            */
  1411. #endif
  1412. X        llp = curwp->w_linep;
  1413. X        dlp = curwp->w_dotp;
  1414. X        while (n-- && lback(dlp)!=curbp->b_linep) {
  1415. X                llp = lback(llp);
  1416. X                dlp = lback(dlp);
  1417. X    }
  1418. X        curwp->w_linep = llp;
  1419. X        curwp->w_dotp  = dlp;
  1420. X    firstnonwhite(f,n);
  1421. X        curwp->w_flag |= WFHARD|WFINS;
  1422. X        return (TRUE);
  1423. }
  1424. X
  1425. X
  1426. X
  1427. /*
  1428. X * Set the named mark in the current window to the value of "." in the window.
  1429. X * No errors are possible.
  1430. X */
  1431. setnmmark(f,n)
  1432. {
  1433. X    char *s;
  1434. X    int c,i;
  1435. X
  1436. X    if (clexec || isnamedcmd) {
  1437. X        int stat;
  1438. X        static char cbuf[2];
  1439. X            if ((stat=mlreply("Set mark: ", cbuf, 2)) != TRUE)
  1440. X                    return stat;
  1441. X        c = cbuf[0];
  1442. X        } else {
  1443. X        c = kbd_key();
  1444. X        }
  1445. X    if (c < 'a' || c > 'z') {
  1446. X        TTbeep();
  1447. X        mlwrite("[Invalid mark name]");
  1448. X        return FALSE;
  1449. X    }
  1450. X        
  1451. X    if (curbp->b_nmmarks == NULL) {
  1452. X        curbp->b_nmmarks = 
  1453. X            (struct MARK *)malloc(26*sizeof(struct MARK));
  1454. X        if (curbp->b_nmmarks == NULL) {
  1455. X            mlwrite("[OUT OF MEMORY]");
  1456. X            return FALSE;
  1457. X        }
  1458. X        for (i = 0; i < 26; i++) {
  1459. X            curbp->b_nmmarks[i].markp = NULL;
  1460. X            curbp->b_nmmarks[i].marko = 0;
  1461. X        }
  1462. X    }
  1463. X        
  1464. X        curbp->b_nmmarks[c-'a'].markp = curwp->w_dotp;
  1465. X        curbp->b_nmmarks[c-'a'].marko = curwp->w_doto;
  1466. X        s = "[Mark X set]";
  1467. X    s[6] = c;
  1468. X        mlwrite(s);
  1469. X        return TRUE;
  1470. }
  1471. X
  1472. golinenmmark(f,n)
  1473. {
  1474. X    int status;
  1475. X    status = goexactnmmark(f,n);
  1476. X    if (status != TRUE)
  1477. X        return(status);
  1478. X    firstnonwhite(f,n);
  1479. X    return(TRUE);
  1480. }
  1481. X
  1482. goexactnmmark(f,n)
  1483. {
  1484. X    int c;
  1485. X    int this1key;
  1486. X    int useldmark;
  1487. X
  1488. X    this1key = last1key;
  1489. X    c = kbd_seq();
  1490. X    useldmark = (last1key == this1key);  /* '' or `` */
  1491. X    c = kcod2key(c);
  1492. X
  1493. X    if (useldmark)
  1494. X        c = '\'';
  1495. X
  1496. X    return gonmmark(c);
  1497. }
  1498. X
  1499. gonmmark(c)
  1500. {
  1501. X    register LINE **markpp;
  1502. X    register int *markop;
  1503. X    LINE *tmarkp;
  1504. X    int tmarko;
  1505. X    int found;
  1506. X
  1507. X    if (!islower(c) && c != '\'') {
  1508. X        TTbeep();
  1509. X        mlwrite("[Invalid mark name]");
  1510. X        return FALSE;
  1511. X    }
  1512. X
  1513. X    markpp = NULL;
  1514. X
  1515. X    if (c == '\'') { /* use the 'last dot' mark */
  1516. X        markpp = &(curwp->w_ldmkp);
  1517. X        markop = &(curwp->w_ldmko);
  1518. X    } else if (curbp->b_nmmarks != NULL) {
  1519. X        markpp = &(curbp->b_nmmarks[c-'a'].markp);
  1520. X         markop = &(curbp->b_nmmarks[c-'a'].marko);
  1521. X    }
  1522. X        
  1523. X    found = FALSE;
  1524. X    if (markpp != NULL && *markpp != NULL) {
  1525. X        register LINE *lp;
  1526. X        for (lp = lforw(curbp->b_linep);
  1527. X                lp != curbp->b_linep; lp = lforw(lp)) {
  1528. X            if (*markpp == lp) {
  1529. X                found = TRUE;
  1530. X                break;
  1531. X            }
  1532. X        }
  1533. X    }
  1534. X    if (!found) {
  1535. X        TTbeep();
  1536. X        mlwrite("[Mark not set]");
  1537. X        return (FALSE);
  1538. X    }
  1539. X    
  1540. X    /* save current dot */
  1541. X    tmarkp = curwp->w_dotp;
  1542. X    tmarko = curwp->w_doto;
  1543. X
  1544. X    /* move to the selected mark */
  1545. X    curwp->w_dotp = *markpp;
  1546. X    curwp->w_doto = *markop;
  1547. X
  1548. X    /* reset last-dot-mark to old dot */
  1549. X    curwp->w_ldmkp = tmarkp;
  1550. X    curwp->w_ldmko = tmarko;
  1551. X
  1552. X        curwp->w_flag |= WFMOVE;
  1553. X        return (TRUE);
  1554. }
  1555. X
  1556. /*
  1557. X * Set the mark in the current window to the value of "." in the window. No
  1558. X * errors are possible.
  1559. X */
  1560. setmark()
  1561. {
  1562. X        curwp->w_mkp = curwp->w_dotp;
  1563. X        curwp->w_mko = curwp->w_doto;
  1564. X        return (TRUE);
  1565. }
  1566. X
  1567. gomark(f,n)
  1568. {
  1569. X        curwp->w_dotp = curwp->w_mkp;
  1570. X        curwp->w_doto = curwp->w_mko;
  1571. X        curwp->w_flag |= WFMOVE;
  1572. X        return (TRUE);
  1573. }
  1574. X
  1575. /* this odd routine puts us at the internal mark, plus an offset of lines */
  1576. /*  n == 1 leaves us at mark, n == 2 one line down, etc. */
  1577. /*  this is for the use of stuttered commands, and line oriented regions */
  1578. godotplus(f,n)
  1579. {
  1580. X    int s;
  1581. X    if (!f || n == 1)
  1582. X            return (TRUE);
  1583. X    if (n < 1)
  1584. X            return (FALSE);
  1585. X    s = forwline(TRUE,n-1);
  1586. X    if (s && curwp->w_dotp == curbp->b_linep)
  1587. X        s = backline(FALSE,1);
  1588. X    return s;
  1589. }
  1590. X
  1591. atmark()
  1592. {
  1593. X        return ((curwp->w_dotp == curwp->w_mkp) && 
  1594. X        (curwp->w_doto == curwp->w_mko));
  1595. }
  1596. X
  1597. /*
  1598. X * Swap the values of "." and "mark" in the current window. This is pretty
  1599. X * easy, bacause all of the hard work gets done by the standard routine
  1600. X * that moves the mark about. The only possible error is "no mark".
  1601. X */
  1602. swapmark()
  1603. {
  1604. X        register LINE   *odotp;
  1605. X        register int    odoto;
  1606. X
  1607. X        if (curwp->w_mkp == NULL) {
  1608. X                mlwrite("No mark in this window");
  1609. X                return (FALSE);
  1610. X        }
  1611. X        odotp = curwp->w_dotp;
  1612. X        odoto = curwp->w_doto;
  1613. X        curwp->w_dotp  = curwp->w_mkp;
  1614. X        curwp->w_doto  = curwp->w_mko;
  1615. X        curwp->w_mkp = odotp;
  1616. X        curwp->w_mko = odoto;
  1617. X        curwp->w_flag |= WFMOVE;
  1618. X        return (TRUE);
  1619. }
  1620. X
  1621. X
  1622. X
  1623. #if    NeWS
  1624. /* SETCURSOR
  1625. X *
  1626. X * Mouse support function.  Put the cursor to the requested location.
  1627. X * The cursor will be put just after the last character of the line if 
  1628. X * requested past the line.  The coordinates are expected in the command
  1629. X * stream.
  1630. X *   In the case of multiple windows, the window indicated by the mouse
  1631. X * is located and made the current window.
  1632. X */
  1633. setcursor()
  1634. {
  1635. int    row, col, pasteol ;
  1636. register LINE    *dlp;
  1637. WINDOW *wp0 ;        /* current window on entry */
  1638. X
  1639. X    row = tgetc() ;
  1640. X    col = tgetc() ;
  1641. X
  1642. /* find the window we are pointing to */
  1643. X    wp0 = curwp ;
  1644. X    while ( row < curwp->w_toprow ||
  1645. X        row > curwp->w_ntrows + curwp->w_toprow ) {
  1646. X        nextwind(FALSE,0) ;
  1647. X        if ( curwp == wp0 ) break ;    /* full circle */
  1648. X    }
  1649. X
  1650. /* move to the right row */
  1651. X    row -= curwp->w_toprow ;
  1652. X    dlp = curwp->w_linep ;            /* get pointer to 1st line */
  1653. X    while ( row-- && (dlp != curbp->b_linep) ) dlp = lforw(dlp) ;
  1654. X    curwp->w_dotp = dlp ;            /* set dot line pointer */
  1655. X
  1656. X    /* now move the dot over until near the requested column */
  1657. X    curgoal = col ;        /* a global for this ?? */
  1658. X    curwp->w_doto = getgoal(dlp) ;
  1659. X    curwp->w_flag |= WFMOVE;
  1660. X    return (TRUE);
  1661. }
  1662. #endif
  1663. SHAR_EOF
  1664. chmod 0444 basic.c ||
  1665. echo 'restore of basic.c failed'
  1666. Wc_c="`wc -c < 'basic.c'`"
  1667. test 20335 -eq "$Wc_c" ||
  1668.     echo 'basic.c: original size 20335, current size' "$Wc_c"
  1669. # ============= bind.c ==============
  1670. echo 'x - extracting bind.c (Text)'
  1671. sed 's/^X//' << 'SHAR_EOF' > 'bind.c' &&
  1672. /*    This file is for functions having to do with key bindings,
  1673. X    descriptions, help commands and startup file.
  1674. X
  1675. X    written 11-feb-86 by Daniel Lawrence
  1676. X                                */
  1677. X
  1678. #include    <stdio.h>
  1679. #include    "estruct.h"
  1680. #include    "edef.h"
  1681. #include    "epath.h"
  1682. X
  1683. /* dummy prefix binding functions */
  1684. extern CMDFUNC f_cntl_af, f_cntl_xf, f_unarg, f_esc;
  1685. X
  1686. /* give me some help!!!! bring up a buffer and read the help file into it */
  1687. help(f, n)
  1688. {
  1689. X    register WINDOW *wp;    /* scaning pointer to windows */
  1690. X    register BUFFER *bp;    /* buffer pointer to help */
  1691. X    char *fname;        /* ptr to file returned by flook() */
  1692. X
  1693. X    /* first check if we are already here */
  1694. X    bp = bfind("[Help]", OK_CREAT, BFSCRTCH);
  1695. X    if (bp == NULL)
  1696. X        return FALSE;
  1697. X
  1698. X    if (bp->b_active == FALSE) { /* never been used */
  1699. X        fname = flook(pathname[1], FL_ANYWHERE);
  1700. X        if (fname == NULL) {
  1701. X            mlwrite("[Sorry, can't find the help information]");
  1702. X            zotbuf(bp);
  1703. X            return(FALSE);
  1704. X        }
  1705. X        /* and read the stuff in */
  1706. X        if (readin(fname, 0, bp, TRUE) == FALSE ||
  1707. X                popupbuff(bp) == FALSE) {
  1708. X            zotbuf(bp);
  1709. X            return(FALSE);
  1710. X        }
  1711. X        strcpy(bp->b_bname,"[Help]");
  1712. X            sprintf(bp->b_fname, "       %s   %s",prognam,version);
  1713. X        bp->b_mode |= MDVIEW;
  1714. X        bp->b_mode &= ~MDEXACT;
  1715. X        bp->b_flag |= BFSCRTCH;
  1716. X    }
  1717. X    return swbuffer(bp);
  1718. }
  1719. X
  1720. #if REBIND
  1721. X
  1722. deskey(f, n)    /* describe the command for a certain key */
  1723. {
  1724. X    register int c;        /* key to describe */
  1725. X    register char *ptr;    /* string pointer to scan output strings */
  1726. X    char outseq[NSTRING];    /* output buffer for command sequence */
  1727. X    char *kcod2prc();
  1728. X
  1729. X    /* prompt the user to type us a key to describe */
  1730. X    mlwrite(": describe-key ");
  1731. X
  1732. X    /* get the command sequence to describe
  1733. X       change it to something we can print as well */
  1734. X
  1735. X    /* check to see if we are executing a command line */
  1736. X    if (clexec) {
  1737. X        char tok[NSTRING];
  1738. X        macarg(tok);    /* get the next token */
  1739. X        c = prc2kcod(tok);
  1740. X    } else {
  1741. X        c = kbd_seq();
  1742. X    }
  1743. X    kcod2prc(c, &outseq[0]);
  1744. X
  1745. X    /* and dump it out */
  1746. X    ostring(outseq);
  1747. X    ostring(" ");
  1748. X
  1749. X    /* find the right ->function */
  1750. X    if ((ptr = fnc2engl(kcod2fnc(c))) == NULL)
  1751. X        ptr = "Not Bound";
  1752. X
  1753. X    /* output the command sequence */
  1754. X    ostring(ptr);
  1755. }
  1756. X
  1757. /* bindkey:    add a new key to the key binding table        */
  1758. X
  1759. bindkey(f, n)
  1760. int f, n;    /* command arguments [IGNORED] */
  1761. {
  1762. X    register int c;        /* command key to bind */
  1763. X    register CMDFUNC *kcmd;    /* ptr to the requested function to bind to */
  1764. X    register KBIND *kbp;    /* pointer into a binding table */
  1765. X    register int found;    /* matched command flag */
  1766. X    char outseq[80];    /* output buffer for keystroke sequence */
  1767. X    char *fnp;
  1768. X    char *kbd_engl();
  1769. X    char *kcod2prc();
  1770. X
  1771. X    /* prompt the user to type in a key to bind */
  1772. X    mlwrite(": bind-to-key ");
  1773. X
  1774. X    /* get the function name to bind it to */
  1775. #if    NeWS
  1776. X    newsimmediateon() ;
  1777. #endif
  1778. X    fnp = kbd_engl();
  1779. #if    NeWS
  1780. X    newsimmediateoff() ;
  1781. #endif
  1782. X
  1783. X    if (fnp == NULL || (kcmd = engl2fnc(fnp)) == NULL) {
  1784. X        mlwrite("[No such function]");
  1785. X        return(FALSE);
  1786. X    }
  1787. X    ostring(" ");
  1788. X    TTflush();
  1789. X
  1790. X    /* get the command sequence to bind */
  1791. X    if (clexec) {
  1792. X        char tok[NSTRING];
  1793. X        macarg(tok);    /* get the next token */
  1794. X        c = prc2kcod(tok);
  1795. X    } else {
  1796. X        /* perhaps we only want a single key, not a sequence */
  1797. X        /*     (see more comments below) */
  1798. X        if ((kcmd == &f_cntl_af) || (kcmd == &f_cntl_xf) ||
  1799. X                (kcmd == &f_unarg) || (kcmd == &f_esc))
  1800. X            c = kbd_key();
  1801. X        else
  1802. X            c = kbd_seq();
  1803. X    }
  1804. X
  1805. X    /* change it to something we can print as well */
  1806. X    kcod2prc(c, &outseq[0]);
  1807. X
  1808. X    /* and dump it out */
  1809. X    ostring(outseq);
  1810. X
  1811. X    /* if the function is a prefix key, i.e. we're changing the definition
  1812. X        of a prefix key, then they typed a dummy function name, which
  1813. X        has been translated into a dummy function pointer */
  1814. X    if (kcmd == &f_cntl_af || kcmd == &f_cntl_xf ||
  1815. X        kcmd == &f_unarg || kcmd == &f_esc) {
  1816. X            register CMDFUNC **cfp;
  1817. X        /* search for an existing binding for the prefix key */
  1818. X        cfp = asciitbl;
  1819. X        found = FALSE;
  1820. X        for (cfp = asciitbl; cfp < &asciitbl[128]; cfp++) {
  1821. X            if (*cfp == kcmd) {
  1822. X                unbindchar(cfp - asciitbl);
  1823. X                break;
  1824. X            }
  1825. X        }
  1826. X
  1827. X        /* reset the appropriate global prefix variable */
  1828. X        if (kcmd == &f_cntl_af)
  1829. X            cntl_a = c;
  1830. X        if (kcmd == &f_cntl_xf)
  1831. X            cntl_x = c;
  1832. X        if (kcmd == &f_unarg)
  1833. X            reptc = c;
  1834. X        if (kcmd == &f_esc)
  1835. X            abortc = c;
  1836. X    }
  1837. X    
  1838. X    if ((c & (CTLA|SPEC|CTLX)) == 0) {
  1839. X        asciitbl[c] = kcmd;
  1840. X    } else {
  1841. X        for(kbp = kbindtbl; kbp->k_cmd && kbp->k_code != c; kbp++)
  1842. X            ;
  1843. X        if (kbp->k_cmd) { /* found it, change it in place */
  1844. X            kbp->k_cmd = kcmd;
  1845. X        } else {
  1846. X            if (kbp >= &kbindtbl[NBINDS-1]) {
  1847. X                mlwrite("Prefixed binding table full");
  1848. X                return(FALSE);
  1849. X            }
  1850. X            kbp->k_code = c;    /* add keycode */
  1851. X            kbp->k_cmd = kcmd; /* and func pointer */
  1852. X            ++kbp;        /* and make sure the next is null */
  1853. X            kbp->k_code = 0;
  1854. X            kbp->k_cmd = NULL;
  1855. X        }
  1856. X    }
  1857. X
  1858. X    return TRUE;
  1859. }
  1860. X
  1861. /* unbindkey:    delete a key from the key binding table    */
  1862. X
  1863. unbindkey(f, n)
  1864. int f, n;    /* command arguments [IGNORED] */
  1865. {
  1866. X    register int c;        /* command key to unbind */
  1867. X    char outseq[80];    /* output buffer for keystroke sequence */
  1868. X    char *kcod2prc();
  1869. X
  1870. X    /* prompt the user to type in a key to unbind */
  1871. X    mlwrite(": unbind-key ");
  1872. X
  1873. X    /* get the command sequence to unbind */
  1874. X    if (clexec) {
  1875. X        char tok[NSTRING];
  1876. X        macarg(tok);    /* get the next token */
  1877. X        c = prc2kcod(tok);
  1878. X    } else {
  1879. X        c = kbd_seq();
  1880. X    }
  1881. X
  1882. X    /* change it to something we can print as well */
  1883. X    kcod2prc(c, &outseq[0]);
  1884. X
  1885. X    /* and dump it out */
  1886. X    ostring(outseq);
  1887. X
  1888. X    /* if it isn't bound, bitch */
  1889. X    if (unbindchar(c) == FALSE) {
  1890. X        mlwrite("[Key not bound]");
  1891. X        return(FALSE);
  1892. X    }
  1893. X    return(TRUE);
  1894. }
  1895. X
  1896. unbindchar(c)
  1897. int c;        /* command key to unbind */
  1898. {
  1899. X    register KBIND *kbp;    /* pointer into the command table */
  1900. X    register KBIND *skbp;    /* saved pointer into the command table */
  1901. X    register int found;    /* matched command flag */
  1902. X
  1903. X    if ((c & (CTLA|SPEC|CTLX)) == 0) {
  1904. X        asciitbl[c] = NULL;
  1905. X    } else {
  1906. X        /* search the table to see if the key exists */
  1907. X        for (kbp = kbindtbl; kbp->k_cmd && kbp->k_code != c; kbp++)
  1908. X            ;
  1909. X
  1910. X        /* if it isn't bound, bitch */
  1911. X        if (kbp->k_cmd == NULL)
  1912. X            return(FALSE);
  1913. X
  1914. X        /* save the pointer and scan to the end of the table */
  1915. X        skbp = kbp;
  1916. X        while (kbp->k_cmd != NULL)
  1917. X            ++kbp;
  1918. X        --kbp;        /* backup to the last legit entry */
  1919. X
  1920. X        /* copy the last entry to the current one */
  1921. X        skbp->k_code = kbp->k_code;
  1922. X        skbp->k_cmd  = kbp->k_cmd;
  1923. X
  1924. X        /* null out the last one */
  1925. X        kbp->k_code = 0;
  1926. X        kbp->k_cmd = NULL;
  1927. X    }
  1928. X    return TRUE;
  1929. }
  1930. X
  1931. /* describe bindings bring up a fake buffer and list the key bindings
  1932. X           into it with view mode            */
  1933. desbind(f, n)
  1934. {
  1935. X    return mkblist(NULL);
  1936. }
  1937. X
  1938. #if    APROP
  1939. apro(f, n)    /* Apropos (List functions that match a substring) */
  1940. {
  1941. X    static char mstring[NSTRING] = 0;    /* string to match cmd names to */
  1942. X        register int    s;
  1943. X
  1944. X
  1945. X    s = mlreply("Apropos string: ", mstring, NSTRING - 1);
  1946. X    if (s != TRUE)
  1947. X        return(s);
  1948. X
  1949. X    return mkblist(mstring);
  1950. }
  1951. #endif
  1952. X
  1953. mkblist(mstring)
  1954. char *mstring;
  1955. {
  1956. X        register BUFFER *bp;
  1957. X        register int    s;
  1958. X
  1959. X    /* create the buffer list buffer   */
  1960. X    bp = bfind("[Binding List]", OK_CREAT, BFSCRTCH);
  1961. X    if (bp == NULL)
  1962. X        return FALSE;
  1963. X    
  1964. X        if ((s=bclear(bp)) != TRUE) /* clear old text (?) */
  1965. X                return (s);
  1966. X        s = buildlist(mstring,bp);
  1967. X    if (s != TRUE || popupbuff(bp) == FALSE) {
  1968. X        mlwrite("[Sorry, can't list. ]");
  1969. X        zotbuf(bp);
  1970. X                return (s);
  1971. X        }
  1972. X        strcpy(bp->b_fname, "");
  1973. X    bp->b_mode |= MDVIEW;
  1974. X    bp->b_flag |= BFSCRTCH;
  1975. X        bp->b_flag &= ~BFCHG;        /* Don't complain!      */
  1976. X        bp->b_active = TRUE;
  1977. X
  1978. X        return TRUE;
  1979. }
  1980. X
  1981. X
  1982. /* build a binding list (limited or full) */
  1983. buildlist(mstring, bp)
  1984. char *mstring;        /* match string if partial list, NULL to list all */
  1985. register BUFFER *bp;    /* buffer to put binding list into */
  1986. {
  1987. #if    ST520 & LATTICE
  1988. #define    register        
  1989. #endif
  1990. X    register WINDOW *wp;    /* scanning pointer to windows */
  1991. X    register KBIND *kbp;    /* pointer into a key binding table */
  1992. X    register CMDFUNC **cfp;    /* pointer into the ascii table */
  1993. X    register NTAB *nptr,*nptr2;    /* pointer into the name table */
  1994. X    char *strp;        /* pointer int string to send */
  1995. X    int cpos;        /* current position to use in outseq */
  1996. X    char outseq[81];    /* output buffer for keystroke sequence */
  1997. X    int i,pass;
  1998. X    char *kcod2prc();
  1999. X
  2000. X
  2001. X    /* let us know this is in progress */
  2002. X    mlwrite("[Building binding list]");
  2003. X
  2004. X    /* build the contents of this window, inserting it line by line */
  2005. X    for (pass = 0; pass < 2; pass++) {
  2006. X        for (nptr = nametbl; nptr->n_name != NULL; ++nptr) {
  2007. X
  2008. X        /* if we've already described this one, move on */
  2009. X        if (nptr->n_cmd->c_flags & LISTED)
  2010. X            continue;
  2011. X
  2012. X        /* try to avoid alphabetizing by the real short names */
  2013. X        if (pass == 0 && strlen(nptr->n_name) <= 2)
  2014. X            continue;
  2015. X
  2016. X        /* add in the command name */
  2017. X        strcpy(outseq,"\"");
  2018. X        strcat(outseq, nptr->n_name);
  2019. X        strcat(outseq,"\"");
  2020. X        cpos = strlen(outseq);
  2021. X        while (cpos < 32)
  2022. X            outseq[cpos++] = ' ';
  2023. X        outseq[cpos] = 0;
  2024. X        
  2025. #if    APROP
  2026. X        /* if we are executing an apropos command
  2027. X           and current string doesn't include the search string */
  2028. X        if (mstring && (strinc(outseq, mstring) == FALSE))
  2029. X                continue;
  2030. #endif
  2031. X        /* look in the simple ascii binding table first */
  2032. X        for(cfp = asciitbl, i = 0; cfp < &asciitbl[128]; cfp++, i++) {
  2033. X            if (*cfp == nptr->n_cmd) {
  2034. X                cpos = kcod2prc(i, &outseq[strlen(outseq)]) -
  2035. X                    outseq;
  2036. X                while(cpos & 7)
  2037. X                    outseq[cpos++] = ' ';
  2038. X                outseq[cpos] = '\0';
  2039. X            }
  2040. X        }
  2041. X        /* then look in the multi-key table */
  2042. X        for(kbp = kbindtbl; kbp->k_cmd; kbp++) {
  2043. X            if (kbp->k_cmd == nptr->n_cmd) {
  2044. X                cpos = 
  2045. X                kcod2prc(kbp->k_code, &outseq[strlen(outseq)]) -
  2046. X                    outseq;
  2047. X                while(cpos & 7)
  2048. X                    outseq[cpos++] = ' ';
  2049. X                outseq[cpos] = '\0';
  2050. X            }
  2051. X        }
  2052. X        /* dump the line */
  2053. X        addline(bp,outseq,-1);
  2054. X
  2055. X        cpos = 0;
  2056. X
  2057. X        /* then look for synonyms */
  2058. X        for (nptr2 = nametbl; nptr2->n_name != NULL; ++nptr2) {
  2059. X            /* if it's the one we're on, skip */
  2060. X            if (nptr2 == nptr)
  2061. X                continue;
  2062. X            /* if it's already been listed, skip */
  2063. X            if (nptr2->n_cmd->c_flags & LISTED)
  2064. X                continue;
  2065. X            /* if it's not a synonym, skip */
  2066. X            if (nptr2->n_cmd != nptr->n_cmd)
  2067. X                continue;
  2068. X            while (cpos < 8)
  2069. X                outseq[cpos++] = ' ';
  2070. X            outseq[cpos] = '\0';
  2071. X            strcat(outseq,"\"");
  2072. X            strcat(outseq,nptr2->n_name);
  2073. X            strcat(outseq,"\"");
  2074. X            addline(bp,outseq,-1);
  2075. X            cpos = 0;    /* and clear the line */
  2076. X
  2077. X        }
  2078. X
  2079. X        nptr->n_cmd->c_flags |= LISTED; /* mark it as already listed */
  2080. X        }
  2081. X    }
  2082. X
  2083. X    for (nptr = nametbl; nptr->n_name != NULL; ++nptr)
  2084. X        nptr->n_cmd->c_flags &= ~LISTED; /* mark it as unlisted */
  2085. X
  2086. X    mlwrite("");    /* clear the mode line */
  2087. X    return(TRUE);
  2088. }
  2089. X
  2090. #if    APROP
  2091. strinc(source, sub)    /* does source include sub? */
  2092. char *source;    /* string to search in */
  2093. char *sub;    /* substring to look for */
  2094. {
  2095. X    char *sp;    /* ptr into source */
  2096. X    char *nxtsp;    /* next ptr into source */
  2097. X    char *tp;    /* ptr into substring */
  2098. X
  2099. X    /* for each character in the source string */
  2100. X    sp = source;
  2101. X    while (*sp) {
  2102. X        tp = sub;
  2103. X        nxtsp = sp;
  2104. X
  2105. X        /* is the substring here? */
  2106. X        while (*tp) {
  2107. X            if (*nxtsp++ != *tp)
  2108. X                break;
  2109. X            else
  2110. X                tp++;
  2111. X        }
  2112. X
  2113. X        /* yes, return a success */
  2114. X        if (*tp == 0)
  2115. X            return(TRUE);
  2116. X
  2117. X        /* no, onward */
  2118. X        sp++;
  2119. X    }
  2120. X    return(FALSE);
  2121. }
  2122. #endif
  2123. X
  2124. #endif /* REBIND */
  2125. X
  2126. X
  2127. /* execute the startup file */
  2128. X
  2129. startup(sfname)
  2130. char *sfname;    /* name of startup file  */
  2131. {
  2132. X    char *fname;    /* resulting file name to execute */
  2133. X
  2134. X    /* look up the startup file */
  2135. X    fname = flook(sfname, FL_HERE_HOME);
  2136. X
  2137. X    /* if it isn't around, don't sweat it */
  2138. X    if (fname == NULL) {
  2139. X        mlwrite("[Can't find startup file %s]",sfname);
  2140. X        return(TRUE);
  2141. X    }
  2142. X
  2143. X    /* otherwise, execute the sucker */
  2144. X    return(dofile(fname));
  2145. }
  2146. X
  2147. /*    Look up the existence of a file along the normal or PATH
  2148. X    environment variable. Look first in the HOME directory if
  2149. X    asked and possible
  2150. */
  2151. X
  2152. char *
  2153. flook(fname, hflag)
  2154. char *fname;    /* base file name to search for */
  2155. int hflag;    /* Look in the HOME environment variable first? */
  2156. {
  2157. X    register char *home;    /* path to home directory */
  2158. X    register char *path;    /* environmental PATH variable */
  2159. X    register char *sp;    /* pointer into path spec */
  2160. X    register int i;        /* index */
  2161. X    static char fspec[NSTRING];    /* full path spec to search */
  2162. X    char *getenv();
  2163. X
  2164. X    /* tak care of special cases */
  2165. X    if (!fname || !fname[0] || isspace(fname[0]))
  2166. X        return NULL;
  2167. X    else if (fname[0] == '!')
  2168. X        return fname;
  2169. X        
  2170. X    /* always try the current directory first */
  2171. X    if (ffropen(fname) == FIOSUC) {
  2172. X        ffclose();
  2173. X        return(fname);
  2174. X    }
  2175. X
  2176. X    if (hflag == FL_HERE)
  2177. X        return NULL;
  2178. X
  2179. #if    ENVFUNC
  2180. X
  2181. X    if (hflag) {
  2182. X        home = getenv("HOME");
  2183. X        if (home != NULL) {
  2184. X            /* build home dir file spec */
  2185. X            strcpy(fspec, home);
  2186. X            strcat(fspec, "/");
  2187. X            strcat(fspec, fname);
  2188. X
  2189. X            /* and try it out */
  2190. X            if (ffropen(fspec) == FIOSUC) {
  2191. X                ffclose();
  2192. X                return(fspec);
  2193. X            }
  2194. X        }
  2195. X    }
  2196. X
  2197. X    if (hflag == FL_HERE_HOME)
  2198. X        return NULL;
  2199. X
  2200. #if PATHLOOK
  2201. X    /* get the PATH variable */
  2202. X    path = getenv("PATH");
  2203. X    if (path != NULL)
  2204. X        while (*path) {
  2205. X
  2206. X            /* build next possible file spec */
  2207. X            sp = fspec;
  2208. X            while (*path && (*path != PATHCHR))
  2209. X                *sp++ = *path++;
  2210. X            *sp++ = '/';
  2211. X            *sp = 0;
  2212. X            strcat(fspec, fname);
  2213. X
  2214. X            /* and try it out */
  2215. X            if (ffropen(fspec) == FIOSUC) {
  2216. X                ffclose();
  2217. X                return(fspec);
  2218. X            }
  2219. X
  2220. X            if (*path == PATHCHR)
  2221. X                ++path;
  2222. X        }
  2223. #endif
  2224. #endif
  2225. X
  2226. X    /* look it up via the old table method */
  2227. X    for (i=2; i < NPNAMES; i++) {
  2228. X        strcpy(fspec, pathname[i]);
  2229. X        strcat(fspec, fname);
  2230. X
  2231. X        /* and try it out */
  2232. X        if (ffropen(fspec) == FIOSUC) {
  2233. X            ffclose();
  2234. X            return(fspec);
  2235. X        }
  2236. X    }
  2237. X
  2238. X
  2239. X    return NULL;    /* no such luck */
  2240. }
  2241. X
  2242. /* translate a 10-bit keycode to its printable name (like "M-j")  */
  2243. char *
  2244. kcod2prc(c, seq)
  2245. int c;        /* sequence to translate */
  2246. char *seq;    /* destination string for sequence */
  2247. {
  2248. X    char *ptr;    /* pointer into current position in sequence */
  2249. X
  2250. X    ptr = seq;
  2251. X
  2252. X    /* apply cntl_a sequence if needed */
  2253. X    if (c & CTLA) {
  2254. X        *ptr++ = '^';
  2255. X        *ptr++ = 'A';
  2256. X        *ptr++ = '-';
  2257. X    }
  2258. X
  2259. X    /* apply ^X sequence if needed */
  2260. X    if (c & CTLX) {
  2261. X        *ptr++ = '^';
  2262. X        *ptr++ = 'X';
  2263. X        *ptr++ = '-';
  2264. X    }
  2265. X
  2266. X    /* apply SPEC sequence if needed */
  2267. X    if (c & SPEC) {
  2268. X        *ptr++ = 'F';
  2269. X        *ptr++ = 'N';
  2270. X        *ptr++ = '-';
  2271. X    }
  2272. X    
  2273. X    c = kcod2key(c);
  2274. X
  2275. X    /* apply control sequence if needed */
  2276. X    if (iscntrl(c)) {
  2277. X        *ptr++ = '^';
  2278. X        c = toalpha(c);
  2279. X    }
  2280. X
  2281. X    /* and output the final sequence */
  2282. X
  2283. X    if (c == ' ') {
  2284. X        *ptr++ = '<';
  2285. X        *ptr++ = 's';
  2286. X        *ptr++ = 'p';
  2287. X        *ptr++ = '>';
  2288. X    } else if (c == '\t') {
  2289. X        *ptr++ = '<';
  2290. X        *ptr++ = 't';
  2291. X        *ptr++ = 'a';
  2292. X        *ptr++ = 'b';
  2293. X        *ptr++ = '>';
  2294. X    } else {
  2295. X        *ptr++ = c;
  2296. X    }
  2297. X    *ptr = 0;    /* terminate the string */
  2298. X    return ptr;
  2299. }
  2300. X
  2301. X
  2302. /* kcod2fnc:  translate a 10-bit keycode to a function pointer */
  2303. /*    (look a key binding up in the binding table)        */
  2304. CMDFUNC *
  2305. kcod2fnc(c)
  2306. int c;    /* key to find what is bound to it */
  2307. {
  2308. X    register KBIND *kbp;
  2309. X
  2310. X    if ((c & (CTLA|SPEC|CTLX)) == 0) {
  2311. X        return asciitbl[c];
  2312. X    } else {
  2313. X        for (kbp = kbindtbl; kbp->k_cmd && kbp->k_code != c; kbp++)
  2314. X            ;
  2315. X        return kbp->k_cmd;
  2316. X    }
  2317. }
  2318. X
  2319. X
  2320. /* fnc2engl: translate a function pointer to the english name for 
  2321. X        that function
  2322. */
  2323. X
  2324. char *
  2325. fnc2engl(cfp)
  2326. CMDFUNC *cfp;    /* ptr to the requested function to bind to */
  2327. {
  2328. X    register NTAB *nptr;    /* pointer into the name table */
  2329. X
  2330. X    /* skim through the table, looking for a match */
  2331. X    for (nptr = nametbl; nptr->n_cmd; nptr++) {
  2332. SHAR_EOF
  2333. true || echo 'restore of bind.c failed'
  2334. echo 'End of Vile part 1'
  2335. echo 'File bind.c is continued in part 2'
  2336. echo 2 > _shar_seq_.tmp
  2337. exit 0
  2338. -- 
  2339.         paul fox, pgf@cayman.com, (617)494-1999
  2340.         Cayman Systems, 26 Landsdowne St., Cambridge, MA 02139
  2341.