home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume11 / stevie3.69a / part06 < prev    next >
Encoding:
Text File  |  1990-03-10  |  60.0 KB  |  2,874 lines

  1. Newsgroups: comp.sources.misc
  2. organization: AT&T Bell Labs - Lincroft, NJ
  3. subject: v11i014: Stevie 3.69a - 6/6
  4. from: dmt@pegasus.ATT.COM (Dave Tutelman)
  5. Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  6.  
  7. Posting-number: Volume 11, Issue 14
  8. Submitted-by: dmt@pegasus.ATT.COM (Dave Tutelman)
  9. Archive-name: stevie3.69a/part06
  10.  
  11. : This is a shar archive.  Extract with sh, not csh.
  12. : The rest of this file will extract:
  13. : dos.c minix.c os2.c unix.c setenv.c ctags.c
  14. echo extracting - dos.c
  15. sed 's/^X//' > dos.c << '!EOR!'
  16. X/* $Header:
  17. X *
  18. X * MSDOS support for Stevie.
  19. X * Many of the functions in this file have two versions:
  20. X *   -    The original version, using ANSI escape sequences
  21. X *    (by Tim Thompson and/or Tony Andrews).
  22. X *    It requires a non-IBM ANSI driver, such as the shareware NANSI.SYS.
  23. X *   -    The BIOS-function version (by Larry A. Shurr).  The BIOS version
  24. X *    doesn't require an enhanced console driver such as NANSI.SYS.
  25. X *    Invoke it by #defining BIOS in ENV.H.
  26. X * Dave Tutelman has incorporated many features of Larry Shurr's BIOS
  27. X * version (such as colors and 43-line mode) into the ANSI version.
  28. X */
  29. X
  30. X#include "stevie.h"
  31. X#include <stdio.h>
  32. X#include <dos.h>
  33. X#include <signal.h>
  34. X
  35. Xchar    *getenv();
  36. X
  37. Xstatic    char    getswitch();
  38. Xstatic    void    setswitch();
  39. X
  40. X#ifdef BIOS
  41. Xvoid bios_t_ed();
  42. Xvoid bios_t_el();
  43. X#endif
  44. X
  45. Xenum hostval_e {hIBMPC, hTIPRO};
  46. Xtypedef enum hostval_e hostval;
  47. Xstatic    hostval    host_type   = 0;    /* Gets host computer type */
  48. X
  49. Xstatic    char    bgn_color   = 0x7;    /* For saving orig color */
  50. Xstatic    char    quitting_now= 0;    /* Set for windexit() */
  51. Xstatic    int    crt_int     = 0;    /* Gets CRT BIOS interrupt */
  52. Xstatic    char    bgn_page    = 0;    /* For saving current page (IBM PC) */
  53. Xstatic    char    bgn_mode    = 0;    /* For saving video mode (IBM PC) */
  54. X
  55. X#ifdef BIOS
  56. Xstatic    int    sav_curattr = 0;    /* For saving cursor attributes */
  57. Xstatic    int    sav_curpos  = 0;    /* For saving cursor position */
  58. X#endif
  59. X
  60. X/*
  61. X * inchar() - get a character from the keyboard
  62. X */
  63. Xint
  64. Xinchar()
  65. X{
  66. X    int    c;
  67. X
  68. X    got_int = FALSE;
  69. X
  70. X    for (;;beep()) {    /* loop until we get a valid character */
  71. X
  72. X        flushbuf();    /* flush any pending output */
  73. X
  74. X        switch (c = getch()) {
  75. X        case 0x1e:
  76. X            return K_CCIRCM;
  77. X        case 0:                /* special key */
  78. X            if (State != NORMAL) {
  79. X                c = getch();    /* throw away next char */
  80. X                continue;    /* and loop for another char */
  81. X            }
  82. X            switch (c = getch()) {
  83. X            case 0x50:
  84. X                return K_DARROW;
  85. X            case 0x48:
  86. X                return K_UARROW;
  87. X            case 0x4b:
  88. X                return K_LARROW;
  89. X            case 0x4d:
  90. X                return K_RARROW;
  91. X            case 0x47:        /* Home key */
  92. X                stuffin("1G");
  93. X                return -1;
  94. X            case 0x4f:        /* End key */
  95. X                stuffin("G");
  96. X                return -1;
  97. X            case 0x51:        /* PgDn key */
  98. X                stuffin(mkstr(CTRL('F')));
  99. X                return -1;
  100. X            case 0x49:        /* PgUp key */
  101. X                stuffin(mkstr(CTRL('B')));
  102. X                return -1;
  103. X            case 0x52:        /* insert key */
  104. X                return K_INSERT;
  105. X            case 0x53:        /* delete key */
  106. X                stuffin("x");
  107. X                return -1;
  108. X            /*
  109. X             * Hard-code some useful function key macros.
  110. X             */
  111. X            case 0x3b: /* F1 */
  112. X                stuffin(":help\n");
  113. X                return -1;
  114. X            case 0x3c: /* F2 */
  115. X                stuffin(":n\n");
  116. X                return -1;
  117. X            case 0x55: /* SF2 */
  118. X                stuffin(":n!\n");
  119. X                return -1;
  120. X            case 0x3d: /* F3 */
  121. X                stuffin(":N\n");
  122. X                return -1;
  123. X            case 0x56: /* SF3 */
  124. X                stuffin(":N!\n");
  125. X                return -1;
  126. X            case 0x3e: /* F4 */
  127. X                stuffin(":e #\n");
  128. X                return -1;
  129. X            case 0x57: /* SF4 */
  130. X                stuffin(":e! #\n");
  131. X                return -1;
  132. X            case 0x3f: /* F5 */
  133. X                stuffin(":rew\n");
  134. X                return -1;
  135. X            case 0x58: /* SF5 */
  136. X                stuffin(":rew!\n");
  137. X                return -1;
  138. X            case 0x40: /* F6 */
  139. X                stuffin("]]");
  140. X                return -1;
  141. X            case 0x59: /* SF6 */
  142. X                stuffin("[[");
  143. X                return -1;
  144. X            case 0x42: /* F8 - Set up global substitute */
  145. X                stuffin(":1,$s/");
  146. X                return -1;
  147. X            case 0x43: /* F9 - declare C variable */
  148. X                stuffin("yyp!!cdecl\n");
  149. X                return -1;
  150. X            case 0x5C: /* SF9 - explain C declaration */
  151. X                stuffin("yyp^iexplain \033!!cdecl\n");
  152. X                return -1;
  153. X            case 0x44: /* F10 - save & quit */
  154. X                stuffin(":x\n");
  155. X                return -1;
  156. X            case 0x5D: /* F10 - quit without saving */
  157. X                stuffin(":q!\n");
  158. X                return -1;
  159. X            default:
  160. X                break;
  161. X            }
  162. X            break;
  163. X
  164. X        default:
  165. X            return c;
  166. X        }
  167. X    }
  168. X}
  169. X
  170. X
  171. Xstatic    int    bpos = 0;
  172. X#ifdef BIOS
  173. X
  174. X#define    BSIZE    256
  175. Xstatic    char    outbuf[BSIZE];
  176. X
  177. X/* Flushbuf() is used a little differently here in the BIOS-only interface
  178. X * than in the case of other systems.  In general, the other systems buffer
  179. X * large amounts of text and screen management data (escape sequences).
  180. X * Here, only text is buffered, screen management is performed using BIOS
  181. X * calls.  Hence, the buffer is much smaller since no more than one line of
  182. X * text is buffered.  Also, screen management calls must assure that the
  183. X * buffered text is output before performing the requested function.
  184. X *
  185. X * O.K.  Now I had better explain the tricky code sequences for IBM PC and
  186. X * TI Pro.  In both cases, the tricks involve: 1) getting the text written
  187. X * to the display as quickly as possible in the desired color and 2) assur-
  188. X * ing that the cursor is positioned immediately following the latest text
  189. X * output.
  190. X *
  191. X * On the IBM PC, we output the first character using the "write character
  192. X * with attribute" function followed by code which outputs the buffer, a
  193. X * character at a time, using the "write tty" function.  The first write
  194. X * sets the display attributes, which are then reused by the "write tty"
  195. X * function.  The "write tty" is then used to quickly write the data while
  196. X * advancing the cursor.  The "write character with attribute" function
  197. X * does not advance the cursor and so cannot be used to write the entire
  198. X * buffer without additional code to advance the cursor in a separate oper-
  199. X * ation.  Even though the first character in each buffer gets written
  200. X * twice, the result is still substantially faster than it would be using a
  201. X * "write character with attribute" - "[re]position cursor" sequence.
  202. X *
  203. X * On the TI Pro, we output the entire buffer using the "write character
  204. X * string with attribute" function which is fast and convenient.  Unfortun-
  205. X * ately, it does not advance the cursor.  Therefore, we include code which
  206. X * determines the current location of the cursor, writes the buffer, then
  207. X * positions the cursor at the end of the new data.
  208. X *
  209. X * I admit it, this is tricky, but it makes display updates much faster
  210. X * than the would be using a more straightforward approach.
  211. X */
  212. X
  213. X
  214. Xvoid
  215. Xflushbuf()                /* Flush buffered output to display */
  216. X{
  217. X    union    REGS    inregs, curregs, outregs;
  218. X
  219. X    if (bpos != 0) {
  220. X        char    *bptr = outbuf;
  221. X
  222. X        switch (host_type) {
  223. X        case hIBMPC:
  224. X            inregs.h.ah = 0x09;
  225. X            inregs.h.al = *bptr;
  226. X            inregs.h.bh = bgn_page;
  227. X            inregs.h.bl = P(P_CO);
  228. X            inregs.x.cx = 1;
  229. X            int86(crt_int, &inregs, &outregs);
  230. X            inregs.h.ah = 0x0E;
  231. X            while (bpos-- > 0) {
  232. X                inregs.h.al = *bptr++;
  233. X                int86(crt_int, &inregs, &outregs);
  234. X            }
  235. X            break;
  236. X        case hTIPRO:
  237. X            curregs.h.ah = 0x03;
  238. X            int86(crt_int, &curregs, &curregs);
  239. X            inregs.h.ah = 0x10;
  240. X            inregs.h.al = P(P_CO);
  241. X            inregs.x.bx = FP_OFF(outbuf);
  242. X            inregs.x.cx = bpos;
  243. X            inregs.x.dx = FP_SEG(outbuf);
  244. X            int86(crt_int, &inregs, &outregs);
  245. X            curregs.h.ah = 0x02;
  246. X            curregs.h.dh += bpos;
  247. X            int86(crt_int, &curregs, &outregs);
  248. X            break;
  249. X        }
  250. X    }
  251. X    bpos = 0;
  252. X}
  253. X
  254. Xvoid
  255. Xwrite_tty(c)                /* Used to execute control chars */
  256. Xchar    c;
  257. X{
  258. X    int    curcol;
  259. X
  260. X    union    REGS    inregs, curregs, outregs;
  261. X
  262. X    flushbuf(); \
  263. X
  264. X    switch (c) {
  265. X    case '\t':
  266. X        inregs.h.ah = 0x09;
  267. X        inregs.h.al = ' ';
  268. X        inregs.h.bh = bgn_page;
  269. X        inregs.h.bl = P(P_CO);
  270. X        inregs.x.cx = 1;
  271. X        int86(crt_int, &inregs, &outregs);
  272. X        inregs.h.ah = 0x0E;
  273. X        int86(crt_int, &inregs, &outregs);
  274. X        curregs.h.ah = 0x03;
  275. X        curregs.h.bh = bgn_page;
  276. X        int86(crt_int, &curregs, &outregs);
  277. X        curcol = host_type == hIBMPC ? outregs.h.dl : outregs.h.dh;
  278. X        while (curcol++ % P(P_TS)) int86(crt_int, &inregs, &outregs);
  279. X        break;
  280. X    case '\n':
  281. X        if (host_type == hTIPRO) bios_t_el();
  282. X        /* No break, fall through to default action. */
  283. X    default:
  284. X        inregs.h.ah = 0x0E;
  285. X        inregs.h.bh = bgn_page;
  286. X        inregs.h.al = c;
  287. X        int86(crt_int, &inregs, &outregs);
  288. X        break;
  289. X    }
  290. X}
  291. X
  292. X#else        /* Not BIOS */
  293. X
  294. X#define    BSIZE    2048
  295. Xstatic    char    outbuf[BSIZE];
  296. X
  297. Xvoid
  298. Xflushbuf()
  299. X{
  300. X    if (bpos != 0)
  301. X        write(1, outbuf, bpos);
  302. X    bpos = 0;
  303. X}
  304. X
  305. X#endif
  306. X
  307. X
  308. X/*
  309. X * Macro to output a character. Used within this file for speed.
  310. X *
  311. X * This macro had to be upgraded for the BIOS-only version because we
  312. X * cannot count on flushbuf() to execute control characters such as
  313. X * end-of-line or tab.  Therefore, when we encounter one, we flush
  314. X * the buffer and call a routine which executes the character.
  315. X */
  316. X
  317. X#ifdef BIOS
  318. X
  319. X#define    outone(cc) {                 \
  320. X  register char ch = cc;             \
  321. X  if (ch >= ' ') {                   \
  322. X    outbuf[bpos++] = ch;             \
  323. X    if (bpos >= BSIZE) flushbuf();   \
  324. X  } else write_tty(ch);              \
  325. X}
  326. X
  327. X#else
  328. X
  329. X#define    outone(c)    outbuf[bpos++] = c; if (bpos >= BSIZE) flushbuf()
  330. X
  331. X#endif
  332. X
  333. X/*
  334. X * Function version for use outside this file.
  335. X */
  336. X
  337. Xvoid
  338. Xoutchar(c)
  339. Xchar    c;
  340. X{
  341. X    outone(c);
  342. X}
  343. X
  344. X/*
  345. X * outstr(s) - write a string to the console
  346. X */
  347. X
  348. Xvoid
  349. Xoutstr(s)
  350. Xchar    *s;
  351. X{
  352. X    while (*s) {
  353. X        outone(*s++);
  354. X    }
  355. X}
  356. X
  357. Xvoid
  358. Xbeep()
  359. X{
  360. X    if ( P(P_VB) )
  361. X        vbeep();
  362. X    else
  363. X        outchar('\007');
  364. X}
  365. X
  366. Xvbeep()        /* "Visual Bell" - reverse color flash */
  367. X{
  368. X    unsigned char oldcolor, revcolor, temp;
  369. X
  370. X    oldcolor = P(P_CO);
  371. X
  372. X    /* put reverse color in revcolor */
  373. X    revcolor = (P(P_CO) & 0x07) << 4;    /* foregnd -> bkgnd */
  374. X    temp     = (P(P_CO) & 0x70) >> 4;    /* bkgnd -> foregnd */
  375. X    revcolor  |= temp;
  376. X
  377. X    /* Flash revcolor, then back */
  378. X    setcolor (revcolor);
  379. X    flushbuf();
  380. X#ifdef TURBOC
  381. X    delay (100);
  382. X#endif
  383. X    setcolor (oldcolor);
  384. X    windgoto (Cursrow, Curscol);
  385. X    flushbuf();
  386. X}
  387. X
  388. X
  389. X#ifndef TURBOC
  390. Xsleep(n)
  391. Xint    n;
  392. X{
  393. X    /*
  394. X     * Should do something reasonable here.
  395. X     */
  396. X}
  397. X#endif
  398. X
  399. Xvoid
  400. Xpause()
  401. X{
  402. X    long    l;
  403. X
  404. X    flushbuf();
  405. X
  406. X#ifdef TURBOC
  407. X    delay (600);    /* "stop" for a fraction of a second */
  408. X#else
  409. X    /*
  410. X     * Should do something better here...
  411. X     */
  412. X    for (l=0; l < 5000 ;l++)
  413. X        ;
  414. X#endif
  415. X}
  416. X
  417. Xvoid
  418. Xsig()
  419. X{
  420. X    signal(SIGINT, sig);
  421. X
  422. X    got_int = TRUE;
  423. X}
  424. X
  425. Xstatic    char    schar;        /* save original switch character */
  426. X
  427. X/*    While Larry Shurr's addition of color and mode support was
  428. X *    dependent on #define BIOS, there's no reason it needs to be.
  429. X *    The BIOS is always there, even if NANSI.SYS isn't.  We'll
  430. X *    use the BIOS where appropriate, and extend support to
  431. X *    all cases of #define DOS.  This is especially true of the
  432. X *    setup in windinit() and the termination in windexit().
  433. X */
  434. X
  435. Xvoid
  436. Xwindinit()
  437. X{
  438. X    union    REGS    regs;
  439. X    struct    SREGS    sregs;
  440. X
  441. X    /* The "SYSROM..." string is a signature in the TI Pro's ROM which
  442. X     * which we can look for to determine whether or not we're running
  443. X     * on a TI Pro.  If we don't find it at F400:800D,
  444. X     * we assume we're running on an IBM PC or clone.
  445. X     * Unfortunately, the signature is actually
  446. X     * the system ROM's copyright notice though you will note that the
  447. X     * year is omitted.  Still, placing it in this program might
  448. X     * inadvertantly make it appear to be an official copyright notice
  449. X     * for THIS program.  Hence, I have surrounded the signature
  450. X     * string with disclaimers.
  451. X     */
  452. X
  453. X        static    char far *disclaimer1 =
  454. X      "The following is *NOT* a copyright notice for this program: ";
  455. X
  456. X    static    char far *ti_sig =
  457. X          "SYSROM (c) Copyright Texas Instruments Inc.";
  458. X
  459. X    static    char far *disclaimer2[] = {
  460. X      "\nInstead, it is a signature string we look for ",
  461. X      "to distinguish the TI Pro computer.\n",
  462. X      "Actually, this program is in the public domain."
  463. X    };
  464. X
  465. X    static char far    *ti_sig_addr = (char far *)0xF400800D;
  466. X    static int ti_sig_len = sizeof(ti_sig) - 1;
  467. X
  468. X    /* Identify the host type.  Look for signature in TI Pro ROM.  If */
  469. X    /* found, set host type to TI Pro, else assume host is an IBM PC. */
  470. X
  471. X    host_type = strncmp(ti_sig, ti_sig_addr, ti_sig_len) ? hIBMPC : hTIPRO;
  472. X
  473. X    /* Next, perform host-dependent initialization. */
  474. X
  475. X    switch (host_type) {
  476. X    case hIBMPC:
  477. X        /* Get the video mode info */
  478. X        crt_int = 0x10;
  479. X        regs.h.ah = 0x0F;
  480. X        int86(crt_int, ®s, ®s);
  481. X        bgn_page = regs.h.bh;
  482. X        bgn_mode = regs.h.al;
  483. X        Columns = regs.h.ah;
  484. X        /*  Find the starting color, and save to restore later */
  485. X        regs.h.ah = 8;        /* Read char/attr BIOS fn */
  486. X        regs.h.bh = bgn_page;
  487. X        int86(crt_int, ®s, ®s);
  488. X        bgn_color = (int) regs.h.ah;
  489. X        P(P_CO) = bgn_color;
  490. X        break;
  491. X    case hTIPRO:
  492. X        Columns = 80;
  493. X        crt_int = 0x49;
  494. X        P(P_CO) = 0x0F;
  495. X        break;
  496. X
  497. X    default:
  498. X        Columns = 80;
  499. X        break;
  500. X    }
  501. X
  502. X    P(P_LI) = Rows = 25;
  503. X
  504. X    schar = getswitch();
  505. X    setswitch('/');
  506. X
  507. X    signal(SIGINT, sig);
  508. X#ifndef BIOS
  509. X    setraw (1);
  510. X#endif
  511. X}
  512. X
  513. Xvoid
  514. Xwindexit(r)
  515. Xint r;
  516. X{
  517. X
  518. X    union    REGS    regs;
  519. X
  520. X    quitting_now = 1;
  521. X
  522. X    /* Restore original color */
  523. X    setcolor (bgn_color);
  524. X
  525. X    if (host_type == hIBMPC) {
  526. X        /* If we've changed any of the setup, reset the mode.
  527. X         * Otherwise, leave stuff on the screen.
  528. X         */
  529. X        regs.h.ah = 0x0F;    /* "Get-mode" BIOS fn */
  530. X        int86(0x10, ®s, ®s);
  531. X        if (bgn_mode != regs.h.al)
  532. X            set_mode (bgn_mode);
  533. X    }
  534. X
  535. X    flushbuf();
  536. X    setswitch(schar);
  537. X#ifndef BIOS
  538. X    setraw(0);
  539. X#endif
  540. X    exit(r);
  541. X}
  542. X
  543. X
  544. X#ifndef BIOS
  545. X/*    Setraw sets the console driver into raw mode, which makes it run
  546. X *    somewhat faster.  Details of the function:
  547. X *    If r=1, remember current mode, and set into raw mode.
  548. X *       r=0, return to the original mode.
  549. X */
  550. X
  551. Xsetraw (r)
  552. X  int    r;
  553. X{
  554. X    static int origr=0;    /* save the original r */
  555. X    union REGS rr;
  556. X
  557. X    /* Do IOCTL call to get current control info */
  558. X    rr.x.ax = 0x4400;    /* Read IOCTL info - DOS fn */
  559. X    rr.x.bx = 1;        /* Handle for stdout */
  560. X    intdos (&rr, &rr);
  561. X
  562. X    /* Save relevant info, and modify for "set" call */
  563. X    if (r) {
  564. X        origr = rr.h.dl & 0x20;        /* save current "raw" bit */
  565. X        rr.h.dl = rr.h.dl | 0x20;    /* set "raw" bit */
  566. X    }
  567. X    else
  568. X        rr.h.dl = (rr.h.dl & (~0x20)) | (origr & 0x20);
  569. X
  570. X    /* Do IOCTL call to set control info */
  571. X    rr.x.ax = 0x4401;    /* Set IOCTL function call */
  572. X    rr.x.bx = 1;        /* Handle for stdout */
  573. X    rr.h.dh = 0;        /* DL already set up */
  574. X    intdos (&rr, &rr);
  575. X}
  576. X#endif
  577. X
  578. X
  579. Xvoid
  580. Xwindgoto(r, c)                /* Move cursor to r'ow & c'olumn */
  581. Xregister int    r, c;
  582. X{
  583. X#ifdef BIOS
  584. X    union    REGS    inregs, outregs;
  585. X
  586. X    if (bpos > 0) flushbuf();
  587. X
  588. X    inregs.h.ah = 0x02;
  589. X
  590. X    switch (host_type) {
  591. X    case hIBMPC :
  592. X        inregs.h.bh = bgn_page;
  593. X        inregs.h.dh = r;
  594. X        inregs.h.dl = c;
  595. X        break;
  596. X    case hTIPRO:
  597. X        inregs.h.dh = c;
  598. X        inregs.h.dl = r;
  599. X        break;
  600. X    }
  601. X
  602. X    int86(crt_int, &inregs, &outregs);
  603. X
  604. X#else        /* Not BIOS */
  605. X
  606. X    r += 1;
  607. X    c += 1;
  608. X
  609. X    /*
  610. X     * Check for overflow once, to save time.
  611. X     */
  612. X    if (bpos + 8 >= BSIZE)
  613. X        flushbuf();
  614. X
  615. X    outbuf[bpos++] = '\033';
  616. X    outbuf[bpos++] = '[';
  617. X    if (r >= 10)
  618. X        outbuf[bpos++] = r/10 + '0';
  619. X    outbuf[bpos++] = r%10 + '0';
  620. X    outbuf[bpos++] = ';';
  621. X    if (c >= 10)
  622. X        outbuf[bpos++] = c/10 + '0';
  623. X    outbuf[bpos++] = c%10 + '0';
  624. X    outbuf[bpos++] = 'H';
  625. X
  626. X#endif
  627. X}
  628. X
  629. XFILE *
  630. Xfopenb(fname, mode)
  631. Xchar    *fname;
  632. Xchar    *mode;
  633. X{
  634. X    FILE    *fopen();
  635. X    char    modestr[16];
  636. X
  637. X    sprintf(modestr, "%sb", mode);
  638. X    return fopen(fname, modestr);
  639. X}
  640. X
  641. Xstatic    char
  642. Xgetswitch()
  643. X{
  644. X    union    REGS    inregs, outregs;
  645. X
  646. X    inregs.h.ah = 0x37;
  647. X    inregs.h.al = 0;
  648. X
  649. X    intdos(&inregs, &outregs);
  650. X
  651. X    return outregs.h.dl;
  652. X}
  653. X
  654. Xstatic    void
  655. Xsetswitch(c)
  656. Xchar    c;
  657. X{
  658. X    union    REGS    inregs, outregs;
  659. X
  660. X    inregs.h.ah = 0x37;
  661. X    inregs.h.al = 1;
  662. X    inregs.h.dl = c;
  663. X
  664. X    intdos(&inregs, &outregs);
  665. X}
  666. X
  667. X#define    PSIZE    128
  668. X
  669. X/*
  670. X * fixname(s) - fix up a dos name
  671. X *
  672. X * Takes a name like:
  673. X *
  674. X *    \x\y\z\base.ext
  675. X *
  676. X * and trims 'base' to 8 characters, and 'ext' to 3.
  677. X */
  678. Xchar *
  679. Xfixname(s)
  680. Xchar    *s;
  681. X{
  682. X    char    *strchr(), *strrchr();
  683. X    static    char    f[PSIZE];
  684. X    char    base[32];
  685. X    char    ext[32];
  686. X    char    *p;
  687. X    int    i;
  688. X
  689. X    strcpy(f, s);
  690. X
  691. X    for (i=0; i < PSIZE ;i++)
  692. X        if (f[i] == '/')
  693. X            f[i] = '\\';
  694. X
  695. X    /*
  696. X     * Split the name into directory, base, extension.
  697. X     */
  698. X    if ((p = strrchr(f, '\\')) != NULL) {
  699. X        strcpy(base, p+1);
  700. X        p[1] = '\0';
  701. X    } else {
  702. X        strcpy(base, f);
  703. X        f[0] = '\0';
  704. X    }
  705. X
  706. X    if ((p = strchr(base, '.')) != NULL) {
  707. X        strcpy(ext, p+1);
  708. X        *p = '\0';
  709. X    } else
  710. X        ext[0] = '\0';
  711. X
  712. X    /*
  713. X     * Trim the base name if necessary.
  714. X     */
  715. X    if (strlen(base) > 8)
  716. X        base[8] = '\0';
  717. X
  718. X    if (strlen(ext) > 3)
  719. X        ext[3] = '\0';
  720. X
  721. X    /*
  722. X     * Paste it all back together
  723. X     */
  724. X    strcat(f, base);
  725. X    strcat(f, ".");
  726. X    strcat(f, ext);
  727. X
  728. X    return f;
  729. X}
  730. X
  731. Xvoid
  732. Xdoshell(cmd)
  733. Xchar    *cmd;
  734. X{
  735. X    if (cmd == NULL)
  736. X        if ((cmd = getenv ("COMSPEC")) == NULL)
  737. X            cmd = "command.com";
  738. X
  739. X    system(cmd);
  740. X    wait_return();
  741. X}
  742. X
  743. X
  744. X/*
  745. X *    setcolor (color)
  746. X *    Set the screen attributes (basically, color) to value co.
  747. X *    The color attributes for a DOS machine are the BIOS colors
  748. X *    for text.  Where BIOS is not defined, we map the Escape
  749. X *    sequences to the NANSI.SYS equivalents of the BIOS colors.
  750. X */
  751. X
  752. Xsetcolor (color)
  753. X  int    color;
  754. X{
  755. X#ifdef BIOS
  756. X    P(P_CO) = host_type == hIBMPC ? color : ((color & 0x17) | 0x08);
  757. X#else
  758. X    unsigned char work;
  759. X
  760. X    /* Send the ANSI define-attribute sequence */
  761. X    outone('\033');
  762. X    outone('[');
  763. X    outone('0');        /* Normal color */
  764. X    outone(';');
  765. X    /* BIOS-to-NANSI color conversion may look a little bizarre.
  766. X     * They have different bit orderings to represent the
  767. X     * color (BIOS=RGB, NANSI=BGR).
  768. X     *
  769. X     * First put the foreground color.
  770. X     */
  771. X    work = 0;
  772. X    if (color & 1)        work += 4;    /* Blue */
  773. X    if (color & 2)        work += 2;    /* Green */
  774. X    if (color & 4)        work += 1;    /* Red */
  775. X    outone('3');        /* NANSI foreground starts at 30 */
  776. X    outone(work + '0');
  777. X    outone(';');
  778. X    /*  Now the background color */
  779. X    work = 0;
  780. X    if (color & 0x10)    work += 4;    /* Blue */
  781. X    if (color & 0x20)    work += 2;    /* Green */
  782. X    if (color & 0x40)    work += 1;    /* Red */
  783. X    outone('4');        /* NANSI background starts at 40 */
  784. X    outone(work + '0');
  785. X    /*  Do the intensity and blinking, if any  */
  786. X    if (color & 8) {    /* intensity */
  787. X        outone(';');
  788. X        outone('1');
  789. X    }
  790. X    if (color & 0x80) {    /* blink */
  791. X        outone(';');
  792. X        outone('5');
  793. X    }
  794. X    /*  The 'm' suffix means "set graphic rendition"  */
  795. X    outone('m');
  796. X    P(P_CO) = color;
  797. X
  798. X#endif        /* Not BIOS */
  799. X
  800. X    if (!quitting_now) {
  801. X        screenclear();
  802. X        updatescreen();
  803. X    }
  804. X}
  805. X
  806. X
  807. X/*    setrows (r)
  808. X *    Sets the screen to "r" rows, or lines, where "r" is a feasible
  809. X *    value for the IBM PC with some common display.  In this function:
  810. X *   -    We set the mode to 25-line or 43-line mode, assuming the display
  811. X *    supports the requested mode.
  812. X *   -    We set the logical number of lines that Stevie uses to "r",
  813. X *    so that the screen USED may not be the same as the physical screen.
  814. X *
  815. X *    The function returns the number of rows set.
  816. X */
  817. Xsetrows (r)
  818. X  int r;
  819. X{
  820. X    int    rphys, rlog;    /* physical and logical "r" */
  821. X
  822. X    rphys = (r <= 25) ? 25 : 43 ;
  823. X    rlog  = (r <= 50) ? r : 50;
  824. X
  825. X    /* Set the mode to correspond to the number of lines */
  826. X    set_mode (rphys);
  827. X
  828. X    return (rlog);
  829. X}
  830. X
  831. X
  832. Xset_mode (m)
  833. X  int m;
  834. X{
  835. X    set_25 ();
  836. X    if (m == 43)
  837. X        set_43 ();
  838. X}
  839. X
  840. X#ifdef BIOS
  841. X
  842. Xint
  843. Xset_25(lines)            /* Set display to 25 line mode */
  844. Xint    lines;
  845. X{
  846. X    union    REGS    inregs, outregs;
  847. X
  848. X    switch (host_type) {
  849. X    case hIBMPC:
  850. X        inregs.h.ah = 0x00;
  851. X        inregs.h.al = bgn_mode;
  852. X        int86(crt_int, &inregs, &outregs);
  853. X        break;
  854. X    case hTIPRO:
  855. X        windgoto(0, 0);
  856. X        inregs.h.ah = 0x09;
  857. X        inregs.h.al = ' ';
  858. X        inregs.h.bl = P(P_CO);
  859. X        inregs.x.cx = 80 * 25;
  860. X        int86(crt_int, &inregs, &outregs);
  861. X        if (lines > 25) lines = 25;
  862. X        break;
  863. X    }
  864. X
  865. X    return(lines);
  866. X}
  867. X
  868. Xint
  869. Xset_43(lines)            /* Set display to 43/50 line mode */
  870. Xint    lines;
  871. X{
  872. X    union    REGS    inregs, outregs;
  873. X
  874. X    switch (host_type) {
  875. X    case hIBMPC:
  876. X        inregs.x.ax = 0x1112;
  877. X        inregs.h.bl = 0;
  878. X        int86(crt_int, &inregs, &outregs);
  879. X        inregs.x.ax = 0x1200;
  880. X        inregs.h.bl = 0x20;
  881. X        int86(crt_int, &inregs, &outregs);
  882. X        inregs.h.ah = 0x01;
  883. X        inregs.x.cx = 0x0707;
  884. X        int86(crt_int, &inregs, &outregs);
  885. X        break;
  886. X    case hTIPRO:
  887. X        if (lines > 25) lines = 25;
  888. X        break;
  889. X    }
  890. X
  891. X    return(lines);
  892. X}
  893. X
  894. X#else        /* Not BIOS */
  895. X
  896. Xset_25 ()
  897. X{
  898. X    send_setmode (bgn_mode);
  899. X}
  900. X
  901. Xset_43 ()
  902. X{
  903. X    send_setmode (43);
  904. X}
  905. X
  906. Xsend_setmode (m)
  907. X{
  908. X    outone('\033');
  909. X    outone('[');
  910. X
  911. X    /* Convert 2-digit decimal to ASCII */
  912. X    if (m >= 10)
  913. X        outone( m/10 + '0' );
  914. X    outone( m%10 + '0' );
  915. X    outone ('h');
  916. X}
  917. X
  918. X#endif        /* Not BIOS */
  919. X
  920. X#ifdef BIOS
  921. X/*
  922. X *    The rest of the file is BIOS-specific
  923. X */
  924. X
  925. Xvoid
  926. Xbios_t_ci()                /* Make cursor invisible */
  927. X{
  928. X    union    REGS    inregs, outregs;
  929. X
  930. X    if (sav_curattr == 0) {
  931. X        inregs.h.ah = 0x03;
  932. X        inregs.h.bh = bgn_page;
  933. X        int86(crt_int, &inregs, &outregs);
  934. X        sav_curattr = outregs.x.cx;
  935. X        inregs.h.ah = 0x01;
  936. X        inregs.x.cx = 0x2000;
  937. X        int86(crt_int, &inregs, &outregs);
  938. X    }
  939. X}
  940. X
  941. Xvoid
  942. Xbios_t_cv()                /* Make cursor visible */
  943. X{
  944. X    union    REGS    inregs, outregs;
  945. X
  946. X    if (sav_curattr != 0) {
  947. X        inregs.h.ah = 0x01;
  948. X        inregs.h.bh = bgn_page;
  949. X        inregs.x.cx = sav_curattr;
  950. X        int86(crt_int, &inregs, &outregs);
  951. X        sav_curattr = 0;
  952. X    }
  953. X}
  954. X
  955. X/*
  956. X * O.K., I have tried to keep bios.c as "pure" as possible. I.e., I have used
  957. X * BIOS calls for everything instead of going for all-out speed by using
  958. X * direct-video access for updating the display - after all, I named it this
  959. X * module bios.c.  There is one area, however, where using the BIOS is just
  960. X * too much of a compromise... the TI Pro's "scroll display" functions are so
  961. X * slow and ugly that I hate them.  True, they are very flexible, but their
  962. X * poor on-screen appearance and low performance are a liability - you prob-
  963. X * ably think I'm exaggerating, but you're wrong - it is truly bad.  There-
  964. X * fore, I am bypassing them and scrolling the screen myself; something I
  965. X * nearly always do.  From a purist like me, that really says something.
  966. X */
  967. X
  968. Xvoid
  969. Xbios_t_dl(r,l)                /* Delete lines */
  970. Xint r, l;
  971. X{
  972. X    char    far    *end;        /* End ptr for TI Pro screen */
  973. X    char    far    *dst;        /* Dest ptr for scrolling TI Pro scrn */
  974. X    char    far    *src;        /* Src  ptr for scrolling TI Pro scrn */
  975. X
  976. X    union    REGS    inregs, outregs;
  977. X
  978. X    switch (host_type) {
  979. X    case hIBMPC:
  980. X        inregs.h.ah = 0x06;
  981. X        inregs.h.al = l;
  982. X        inregs.h.bh = P(P_CO);
  983. X        inregs.h.ch = r;
  984. X        inregs.h.cl = 0;
  985. X        inregs.h.dh = Rows - 1;
  986. X        inregs.h.dl = Columns - 1;
  987. X        int86(crt_int, &inregs, &outregs);
  988. X        break;
  989. X    case hTIPRO:
  990. X        inregs.h.ah = 0x17;
  991. X        int86(crt_int, &inregs, &outregs);
  992. X        dst = MK_FP(0xDE00, outregs.x.dx + (r * Columns));
  993. X        src = dst + (l * Columns);
  994. X        end = MK_FP(0xDE00, outregs.x.dx + ((Rows - 1) * Columns));
  995. X        while (src < end) *dst++ = *src++;
  996. X        while (dst < end) *dst++ = ' ';
  997. X        break;
  998. X    }
  999. X}
  1000. X
  1001. Xvoid
  1002. Xbios_t_ed()                /* Home cursor, erase display */
  1003. X{
  1004. X    union    REGS    inregs, outregs;
  1005. X
  1006. X    windgoto(0, 0);
  1007. X
  1008. X    inregs.h.ah = 0x09;
  1009. X    inregs.h.al = ' ';
  1010. X    inregs.h.bh = bgn_page;
  1011. X    inregs.h.bl = P(P_CO);
  1012. X    inregs.x.cx = Columns * Rows;
  1013. X    int86(crt_int, &inregs, &outregs);
  1014. X}
  1015. X
  1016. Xvoid
  1017. Xbios_t_el()                /* Erase to end-of-line */
  1018. X{
  1019. X    short    ccol;
  1020. X
  1021. X    union    REGS    inregs, outregs;
  1022. X
  1023. X    inregs.h.ah = 0x03;
  1024. X    inregs.h.bh = bgn_page;
  1025. X    int86(crt_int, &inregs, &outregs);
  1026. X
  1027. X    inregs.h.ah = 0x09;
  1028. X    inregs.h.al = ' ';
  1029. X    inregs.h.bl = P(P_CO);
  1030. X
  1031. X    ccol = host_type == hIBMPC ? outregs.h.dl : outregs.h.dh;
  1032. X
  1033. X    inregs.x.cx = Columns - ccol;
  1034. X    int86(crt_int, &inregs, &outregs);
  1035. X}
  1036. X
  1037. X/* As in the delete-line function, we scroll the TI display ourselves
  1038. X * rather than the use the slow-and-ugly software scroll in the BIOS.  See
  1039. X * the remarks for bios_t_dl() additional information.
  1040. X */
  1041. X
  1042. Xvoid
  1043. Xbios_t_il(r,l)                /* Insert lines */
  1044. Xint r, l;
  1045. X{
  1046. X    char    far    *end;        /* End ptr for TI Pro screen */
  1047. X    char    far    *dst;        /* For scrolling TI Pro screen */
  1048. X    char    far    *src;        /* For scrolling TI Pro screen */
  1049. X
  1050. X    union    REGS    inregs, outregs;
  1051. X
  1052. X    switch (host_type) {
  1053. X    case hIBMPC:
  1054. X        inregs.h.ah = 0x07;
  1055. X        inregs.h.al = l;
  1056. X        inregs.h.bh = P(P_CO);
  1057. X        inregs.h.ch = r;
  1058. X        inregs.h.cl = 0;
  1059. X        inregs.h.dh = Rows - 1;
  1060. X        inregs.h.dl = Columns - 1;
  1061. X        int86(crt_int, &inregs, &outregs);
  1062. X        break;
  1063. X    case hTIPRO:
  1064. X        inregs.h.ah = 0x17;
  1065. X        int86(crt_int, &inregs, &outregs);
  1066. X        dst = MK_FP(0xDE00, outregs.x.dx + (Columns * (Rows - 1)) - 1);
  1067. X        src = dst - (Columns * l);
  1068. X        end = MK_FP(0xDE00, outregs.x.dx + (Columns * r));
  1069. X        while (src >= end) *dst-- = *src--;
  1070. X        src = MK_FP(0xDE00, outregs.x.dx + (r * Columns));
  1071. X        end = src + (l * Columns);
  1072. X        while (src < end) *src++ = ' ';
  1073. X        break;
  1074. X    }
  1075. X}
  1076. X
  1077. Xvoid
  1078. Xbios_t_rc()                /* Restore saved cursor position */
  1079. X{
  1080. X    union    REGS    inregs, outregs;
  1081. X
  1082. X    inregs.h.ah = 0x02;
  1083. X    inregs.h.bh = bgn_page;
  1084. X    inregs.x.dx = sav_curpos;
  1085. X    int86(crt_int, &inregs, &outregs);
  1086. X}
  1087. X
  1088. Xvoid
  1089. Xbios_t_sc()                /* Save cursor position */
  1090. X{
  1091. X    union    REGS    inregs, outregs;
  1092. X
  1093. X    inregs.h.ah = 0x03;
  1094. X    inregs.h.bh = bgn_page;
  1095. X    int86(crt_int, &inregs, &outregs);
  1096. X    sav_curpos = outregs.x.dx;
  1097. X}
  1098. X
  1099. X#endif
  1100. X
  1101. !EOR!
  1102. echo extracting - minix.c
  1103. sed 's/^X//' > minix.c << '!EOR!'
  1104. X/* $Header: /nw/tony/src/stevie/src/RCS/minix.c,v 1.5 89/07/11 21:24:18 tony Exp $
  1105. X *
  1106. X * System-dependent routines for Minix-ST
  1107. X */
  1108. X
  1109. X#include "stevie.h"
  1110. X#include <sgtty.h>
  1111. X#include <signal.h>
  1112. X
  1113. X/*
  1114. X * inchar() - get a character from the keyboard
  1115. X */
  1116. Xint
  1117. Xinchar()
  1118. X{
  1119. X    char    c;
  1120. X
  1121. X    flushbuf();        /* flush any pending output */
  1122. X
  1123. X    while (read(0, &c, 1) != 1)
  1124. X        ;
  1125. X
  1126. X    got_int = FALSE;
  1127. X    return c;
  1128. X}
  1129. X
  1130. X#define    BSIZE    2048
  1131. Xstatic    char    outbuf[BSIZE];
  1132. Xstatic    int    bpos = 0;
  1133. X
  1134. Xvoid
  1135. Xflushbuf()
  1136. X{
  1137. X    if (bpos != 0)
  1138. X        write(1, outbuf, bpos);
  1139. X    bpos = 0;
  1140. X}
  1141. X
  1142. X/*
  1143. X * Macro to output a character. Used within this file for speed.
  1144. X */
  1145. X#define    outone(c)    outbuf[bpos++] = c; if (bpos >= BSIZE) flushbuf()
  1146. X
  1147. X/*
  1148. X * Function version for use outside this file.
  1149. X */
  1150. Xvoid
  1151. Xoutchar(c)
  1152. Xregister char    c;
  1153. X{
  1154. X    outbuf[bpos++] = c;
  1155. X    if (bpos >= BSIZE)
  1156. X        flushbuf();
  1157. X}
  1158. X
  1159. Xvoid
  1160. Xoutstr(s)
  1161. Xregister char    *s;
  1162. X{
  1163. X    while (*s) {
  1164. X        outone(*s++);
  1165. X    }
  1166. X}
  1167. X
  1168. Xvoid
  1169. Xbeep()
  1170. X{
  1171. X    if ( P(P_VB) )
  1172. X        vbeep();
  1173. X    else
  1174. X        outone('\007');
  1175. X}
  1176. X
  1177. X/*
  1178. X * remove(file) - remove a file
  1179. X */
  1180. Xvoid
  1181. Xremove(file)
  1182. Xchar *file;
  1183. X{
  1184. X    unlink(file);
  1185. X}
  1186. X
  1187. X/*
  1188. X * rename(of, nf) - rename existing file 'of' to 'nf'
  1189. X */
  1190. Xvoid
  1191. Xrename(of, nf)
  1192. Xchar    *of, *nf;
  1193. X{
  1194. X    unlink(nf);
  1195. X    link(of, nf);
  1196. X    unlink(of);
  1197. X}
  1198. X
  1199. Xvoid
  1200. Xpause()
  1201. X{
  1202. X    sleep (1);
  1203. X}
  1204. X
  1205. Xstatic    struct    sgttyb    ostate;
  1206. X
  1207. X/*
  1208. X * Go into cbreak mode
  1209. X */
  1210. Xvoid
  1211. Xset_tty()
  1212. X{
  1213. X    struct    sgttyb    nstate;
  1214. X
  1215. X     ioctl(0, TIOCGETP, &ostate);
  1216. X     nstate = ostate;
  1217. X     nstate.sg_flags &= ~(XTABS|ECHO);
  1218. X     nstate.sg_flags |= CBREAK;
  1219. X     ioctl(0, TIOCSETP, &nstate);
  1220. X}
  1221. X
  1222. X/*
  1223. X * Restore original terminal modes
  1224. X */
  1225. Xvoid
  1226. Xreset_tty()
  1227. X{
  1228. X    ioctl(0, TIOCSETP, &ostate);
  1229. X}
  1230. X
  1231. Xvoid
  1232. Xsig()
  1233. X{
  1234. X    signal(SIGINT, sig);
  1235. X    signal(SIGQUIT, sig);
  1236. X
  1237. X    got_int = TRUE;
  1238. X}
  1239. X
  1240. Xvoid
  1241. Xwindinit()
  1242. X{
  1243. X#ifdef    TERMCAP
  1244. X    if (t_init() != 1) {
  1245. X        fprintf(stderr, "unknown terminal type\n");
  1246. X        exit(1);
  1247. X    }
  1248. X#else
  1249. X    Columns = 80;
  1250. X    P(P_LI) = Rows = 25;
  1251. X#endif
  1252. X    /*
  1253. X     * The code here makes sure that there isn't a window during which
  1254. X     * we could get interrupted and exit with the tty in a weird state.
  1255. X     */
  1256. X    signal(SIGINT, sig);
  1257. X    signal(SIGQUIT, sig);
  1258. X
  1259. X    set_tty();
  1260. X
  1261. X    if (got_int)
  1262. X        windexit(0);
  1263. X}
  1264. X
  1265. Xvoid
  1266. Xwindexit(r)
  1267. Xint r;
  1268. X{
  1269. X    reset_tty();
  1270. X    exit(r);
  1271. X}
  1272. X
  1273. Xvoid
  1274. Xwindgoto(r, c)
  1275. Xregister int    r, c;
  1276. X{
  1277. X#ifdef    TERMCAP
  1278. X    char    *tgoto();
  1279. X#else
  1280. X    r += 1;
  1281. X    c += 1;
  1282. X#endif
  1283. X
  1284. X    /*
  1285. X     * Check for overflow once, to save time.
  1286. X     */
  1287. X    if (bpos + 8 >= BSIZE)
  1288. X        flushbuf();
  1289. X
  1290. X#ifdef    TERMCAP
  1291. X    outstr(tgoto(T_CM, c, r));
  1292. X#else
  1293. X    outbuf[bpos++] = '\033';
  1294. X    outbuf[bpos++] = '[';
  1295. X    if (r >= 10)
  1296. X        outbuf[bpos++] = r/10 + '0';
  1297. X    outbuf[bpos++] = r%10 + '0';
  1298. X    outbuf[bpos++] = ';';
  1299. X    if (c >= 10)
  1300. X        outbuf[bpos++] = c/10 + '0';
  1301. X    outbuf[bpos++] = c%10 + '0';
  1302. X    outbuf[bpos++] = 'H';
  1303. X#endif
  1304. X}
  1305. X
  1306. XFILE *
  1307. Xfopenb(fname, mode)
  1308. Xchar    *fname;
  1309. Xchar    *mode;
  1310. X{
  1311. X    return fopen(fname, mode);
  1312. X}
  1313. X
  1314. Xchar *
  1315. Xstrchr(s, c)
  1316. Xchar    *s;
  1317. Xchar    c;
  1318. X{
  1319. X    char *index();
  1320. X
  1321. X    return index(s, c);
  1322. X}
  1323. X
  1324. Xchar *
  1325. Xfixname(s)
  1326. Xchar    *s;
  1327. X{
  1328. X    return s;
  1329. X}
  1330. X
  1331. X/*
  1332. X * doshell() - run a command or an interactive shell
  1333. X */
  1334. Xvoid
  1335. Xdoshell(cmd)
  1336. Xchar    *cmd;
  1337. X{
  1338. X    char    *cp, *getenv();
  1339. X    char    cline[128];
  1340. X
  1341. X    outstr("\r\n");
  1342. X    flushbuf();
  1343. X
  1344. X    if (cmd == NULL) {
  1345. X        if ((cmd = getenv("SHELL")) == NULL)
  1346. X            cmd = "/bin/sh";
  1347. X        sprintf(cline, "%s -i", cmd);
  1348. X        cmd = cline;
  1349. X    }
  1350. X
  1351. X    reset_tty();
  1352. X    system(cmd);
  1353. X    set_tty();
  1354. X
  1355. X    wait_return();
  1356. X}
  1357. X
  1358. X/*
  1359. X *    FILL IT IN, FOR YOUR SYSTEM, AND SHARE IT!
  1360. X *
  1361. X *    The next couple of functions do system-specific stuff.
  1362. X *    They currently do nothing; I'm not familiar enough with
  1363. X *    system-specific programming on this system.
  1364. X *    If you fill it in for your system, please post the results
  1365. X *    and share with the rest of us.
  1366. X */
  1367. X
  1368. X
  1369. Xsetcolor (c)
  1370. X/*
  1371. X * Set the color to c, using the local system convention for numbering
  1372. X * colors or video attributes.
  1373. X *
  1374. X * If you implement this, remember to note the original color in
  1375. X * windinit(), before you do any setcolor() commands, and
  1376. X * do a setcolor() back to the original as part of windexit().
  1377. X */
  1378. X  int c:
  1379. X{
  1380. X}
  1381. X
  1382. X
  1383. Xsetrows (r)
  1384. X/*
  1385. X * Set the number of lines to r, if possible.  Otherwise
  1386. X * "do the right thing".  Return the number of lines actually set.
  1387. X *
  1388. X * If you implement this, remember to note the original number of rows
  1389. X * in windinit(), before you do any setrows() commands, and
  1390. X * do a setrows() back to the original as part of windexit().
  1391. X */
  1392. X  int r;
  1393. X{
  1394. X    /* Since we do nothing, just return the current number of lines */
  1395. X    return ( P(P_LI) );
  1396. X}
  1397. X
  1398. X
  1399. Xvbeep ()
  1400. X/*
  1401. X * Do a "visual bell".  This generally consists of flashing the screen
  1402. X * once in inverse video.
  1403. X */
  1404. X{
  1405. X    int    color, revco;
  1406. X
  1407. X    color = P( P_CO );        /* get current color */
  1408. X    revco = reverse_color (color);    /* system-specific */
  1409. X    setcolor (revco);
  1410. X    flushbuf ();
  1411. X    pause ();
  1412. X    setcolor (color);
  1413. X    windgoto (Cursrow, Curscol);
  1414. X    flushbuf ();
  1415. X}
  1416. X
  1417. Xreverse_color (co)
  1418. X/*
  1419. X * Returns the inverse video attribute or color of co.
  1420. X * The existing code below is VERY simple-minded.
  1421. X * Replace it with proper code for your system.
  1422. X */
  1423. X int co;
  1424. X{
  1425. X    if (co)        return (0);
  1426. X    else        return (1);
  1427. X}
  1428. X
  1429. X
  1430. X/********** End of do-it-yourself kit **********************/
  1431. X
  1432. !EOR!
  1433. echo extracting - os2.c
  1434. sed 's/^X//' > os2.c << '!EOR!'
  1435. X/* $Header: /nw/tony/src/stevie/src/RCS/os2.c,v 1.7 89/08/07 05:49:19 tony Exp $
  1436. X *
  1437. X * OS/2 System-dependent routines.
  1438. X */
  1439. X
  1440. X#define    INCL_BASE
  1441. X#include <os2.h>
  1442. X#include <signal.h>
  1443. X#include "stevie.h"
  1444. X
  1445. X/*
  1446. X * inchar() - get a character from the keyboard
  1447. X */
  1448. Xint
  1449. Xinchar()
  1450. X{
  1451. X    register int    c;
  1452. X
  1453. X    got_int = FALSE;
  1454. X
  1455. X    for (;;beep()) {    /* loop until we get a valid character */
  1456. X
  1457. X        flushbuf();    /* flush any pending output */
  1458. X
  1459. X        switch (c = getch()) {
  1460. X        case 0x1e:
  1461. X            return K_CCIRCM;
  1462. X        case 0:                /* special key */
  1463. X            if (State != NORMAL) {
  1464. X                c = getch();    /* throw away next char */
  1465. X                continue;    /* and loop for another char */
  1466. X            }
  1467. X            switch (c = getch()) {
  1468. X            case 0x50:
  1469. X                return K_DARROW;
  1470. X            case 0x48:
  1471. X                return K_UARROW;
  1472. X            case 0x4b:
  1473. X                return K_LARROW;
  1474. X            case 0x4d:
  1475. X                return K_RARROW;
  1476. X            case 0x52:
  1477. X                return K_INSERT;
  1478. X            case 0x47:        /* Home key */
  1479. X                stuffin("1G");
  1480. X                return -1;
  1481. X            case 0x4f:        /* End key */
  1482. X                stuffin("G");
  1483. X                return -1;
  1484. X            case 0x51:        /* PgDn key */
  1485. X                stuffin(mkstr(CTRL('F')));
  1486. X                return -1;
  1487. X            case 0x49:        /* PgUp key */
  1488. X                stuffin(mkstr(CTRL('B')));
  1489. X                return -1;
  1490. X            case 0x52:        /* insert key */
  1491. X                return K_INSERT;
  1492. X            case 0x53:        /* delete key */
  1493. X                stuffin("x");
  1494. X                return -1;
  1495. X            /*
  1496. X             * Hard-code some useful function key macros.
  1497. X             */
  1498. X            case 0x3b: /* F1 */
  1499. X                stuffin(":help\n");
  1500. X                return -1;
  1501. X            case 0x3c: /* F2 */
  1502. X                stuffin(":n\n");
  1503. X                return -1;
  1504. X            case 0x55: /* SF2 */
  1505. X                stuffin(":n!\n");
  1506. X                return -1;
  1507. X            case 0x3d: /* F3 */
  1508. X                stuffin(":N\n");
  1509. X                return -1;
  1510. X            case 0x56: /* SF3 */
  1511. X                stuffin(":N!\n");
  1512. X                return -1;
  1513. X            case 0x3e: /* F4 */
  1514. X                stuffin(":e #\n");
  1515. X                return -1;
  1516. X            case 0x57: /* SF4 */
  1517. X                stuffin(":e! #\n");
  1518. X                return -1;
  1519. X            case 0x3f: /* F5 */
  1520. X                stuffin(":rew\n");
  1521. X                return -1;
  1522. X            case 0x58: /* SF5 */
  1523. X                stuffin(":rew!\n");
  1524. X                return -1;
  1525. X            case 0x40: /* F6 */
  1526. X                stuffin("]]");
  1527. X                return -1;
  1528. X            case 0x59: /* SF6 */
  1529. X                stuffin("[[");
  1530. X                return -1;
  1531. X            case 0x42: /* F8 - Set up global substitute */
  1532. X                stuffin(":1,$s/");
  1533. X                return -1;
  1534. X            case 0x43: /* F9 - declare C variable */
  1535. X                stuffin("yyp!!cdecl\n");
  1536. X                return -1;
  1537. X            case 0x5C: /* SF9 - explain C declaration */
  1538. X                stuffin("yyp^iexplain \033!!cdecl\n");
  1539. X                return -1;
  1540. X            case 0x44: /* F10 - save & quit */
  1541. X                stuffin(":x\n");
  1542. X                return -1;
  1543. X            case 0x5D: /* F10 - quit without saving */
  1544. X                stuffin(":q!\n");
  1545. X                return -1;
  1546. X            default:
  1547. X                break;
  1548. X            }
  1549. X            break;
  1550. X
  1551. X        default:
  1552. X            return c;
  1553. X        }
  1554. X    }
  1555. X}
  1556. X
  1557. X#define    BSIZE    2048
  1558. Xstatic    char    outbuf[BSIZE];
  1559. Xstatic    int    bpos = 0;
  1560. X
  1561. Xvoid
  1562. Xflushbuf()
  1563. X{
  1564. X    if (bpos != 0)
  1565. X        write(1, outbuf, bpos);
  1566. X    bpos = 0;
  1567. X}
  1568. X
  1569. X/*
  1570. X * Macro to output a character. Used within this file for speed.
  1571. X */
  1572. X#define    outone(c)    outbuf[bpos++] = c; if (bpos >= BSIZE) flushbuf()
  1573. X
  1574. X/*
  1575. X * Function version for use outside this file.
  1576. X */
  1577. Xvoid
  1578. Xoutchar(c)
  1579. Xregister char    c;
  1580. X{
  1581. X    outbuf[bpos++] = c;
  1582. X    if (bpos >= BSIZE)
  1583. X        flushbuf();
  1584. X}
  1585. X
  1586. Xstatic    char    cell[2] = { 0, 7 };
  1587. X
  1588. X/*
  1589. X * outstr(s) - write a string to the console
  1590. X *
  1591. X * We implement insert/delete line escape sequences here. This is kind
  1592. X * of a kludge, but at least it's localized to a single point.
  1593. X */
  1594. Xvoid
  1595. Xoutstr(s)
  1596. Xregister char    *s;
  1597. X{
  1598. X    if (strcmp(s, T_DL) == 0) {        /* delete line */
  1599. X        int    r, c;
  1600. X
  1601. X        flushbuf();
  1602. X        VioGetCurPos(&r, &c, 0);
  1603. X        VioScrollUp(r, 0, 100, 100, 1, cell, 0);
  1604. X        return;
  1605. X    }
  1606. X    if (strcmp(s, T_IL) == 0) {        /* insert line */
  1607. X        int    r, c;
  1608. X
  1609. X        flushbuf();
  1610. X        VioGetCurPos(&r, &c, 0);
  1611. X        VioScrollDn(r, 0, 100, 100, 1, cell, 0);
  1612. X        return;
  1613. X    }
  1614. X
  1615. X    while (*s) {
  1616. X        outone(*s++);
  1617. X    }
  1618. X}
  1619. X
  1620. Xvoid
  1621. Xbeep()
  1622. X{
  1623. X    in ( P(P_VB) )
  1624. X        vbeep();
  1625. X    else
  1626. X        outone('\007');
  1627. X}
  1628. X
  1629. Xsleep(n)
  1630. Xint    n;
  1631. X{
  1632. X    DosSleep(1000L * n);
  1633. X}
  1634. X
  1635. Xvoid
  1636. Xpause()
  1637. X{
  1638. X    flushbuf();
  1639. X    DosSleep(300L);
  1640. X}
  1641. X
  1642. Xvoid
  1643. Xsig()
  1644. X{
  1645. X    signal(SIGINT, sig);
  1646. X
  1647. X    got_int = TRUE;
  1648. X}
  1649. X
  1650. Xvoid
  1651. Xwindinit()
  1652. X{
  1653. X    Columns = 80;
  1654. X    P(P_LI) = Rows = 25;
  1655. X
  1656. X    signal(SIGINT, sig);
  1657. X}
  1658. X
  1659. Xvoid
  1660. Xwindexit(r)
  1661. Xint r;
  1662. X{
  1663. X    flushbuf();
  1664. X    exit(r);
  1665. X}
  1666. X
  1667. Xvoid
  1668. Xwindgoto(r, c)
  1669. Xregister int    r, c;
  1670. X{
  1671. X    r += 1;
  1672. X    c += 1;
  1673. X
  1674. X    /*
  1675. X     * Check for overflow once, to save time.
  1676. X     */
  1677. X    if (bpos + 8 >= BSIZE)
  1678. X        flushbuf();
  1679. X
  1680. X    outbuf[bpos++] = '\033';
  1681. X    outbuf[bpos++] = '[';
  1682. X    if (r >= 10)
  1683. X        outbuf[bpos++] = r/10 + '0';
  1684. X    outbuf[bpos++] = r%10 + '0';
  1685. X    outbuf[bpos++] = ';';
  1686. X    if (c >= 10)
  1687. X        outbuf[bpos++] = c/10 + '0';
  1688. X    outbuf[bpos++] = c%10 + '0';
  1689. X    outbuf[bpos++] = 'H';
  1690. X}
  1691. X
  1692. XFILE *
  1693. Xfopenb(fname, mode)
  1694. Xchar    *fname;
  1695. Xchar    *mode;
  1696. X{
  1697. X    FILE    *fopen();
  1698. X    char    modestr[16];
  1699. X
  1700. X    sprintf(modestr, "%sb", mode);
  1701. X    return fopen(fname, modestr);
  1702. X}
  1703. X
  1704. X#define    PSIZE    128
  1705. X
  1706. X/*
  1707. X * fixname(s) - fix up a dos name
  1708. X *
  1709. X * Takes a name like:
  1710. X *
  1711. X *    \x\y\z\base.ext
  1712. X *
  1713. X * and trims 'base' to 8 characters, and 'ext' to 3.
  1714. X */
  1715. Xchar *
  1716. Xfixname(s)
  1717. Xchar    *s;
  1718. X{
  1719. X    char    *strchr(), *strrchr();
  1720. X    static    char    f[PSIZE];
  1721. X    char    base[32];
  1722. X    char    ext[32];
  1723. X    char    *p;
  1724. X    int    i;
  1725. X
  1726. X    strcpy(f, s);
  1727. X
  1728. X    for (i=0; i < PSIZE ;i++)
  1729. X        if (f[i] == '/')
  1730. X            f[i] = '\\';
  1731. X
  1732. X    /*
  1733. X     * Split the name into directory, base, extension.
  1734. X     */
  1735. X    if ((p = strrchr(f, '\\')) != NULL) {
  1736. X        strcpy(base, p+1);
  1737. X        p[1] = '\0';
  1738. X    } else {
  1739. X        strcpy(base, f);
  1740. X        f[0] = '\0';
  1741. X    }
  1742. X
  1743. X    if ((p = strchr(base, '.')) != NULL) {
  1744. X        strcpy(ext, p+1);
  1745. X        *p = '\0';
  1746. X    } else
  1747. X        ext[0] = '\0';
  1748. X
  1749. X    /*
  1750. X     * Trim the base name if necessary.
  1751. X     */
  1752. X    if (strlen(base) > 8)
  1753. X        base[8] = '\0';
  1754. X    
  1755. X    if (strlen(ext) > 3)
  1756. X        ext[3] = '\0';
  1757. X
  1758. X    /*
  1759. X     * Paste it all back together
  1760. X     */
  1761. X    strcat(f, base);
  1762. X    strcat(f, ".");
  1763. X    strcat(f, ext);
  1764. X
  1765. X    return f;
  1766. X}
  1767. X
  1768. Xvoid
  1769. Xdoshell(cmd)
  1770. Xchar    *cmd;
  1771. X{
  1772. X    if (cmd == NULL)
  1773. X        cmd = "cmd.exe";
  1774. X
  1775. X    system(cmd);
  1776. X    wait_return();
  1777. X}
  1778. X
  1779. X/*
  1780. X *    FILL IT IN, FOR YOUR SYSTEM, AND SHARE IT!
  1781. X *
  1782. X *    The next couple of functions do system-specific stuff.
  1783. X *    They currently do nothing; I'm not familiar enough with
  1784. X *    system-specific programming on this system.
  1785. X *    If you fill it in for your system, please post the results
  1786. X *    and share with the rest of us.
  1787. X */
  1788. X
  1789. X
  1790. Xsetcolor (c)
  1791. X/*
  1792. X * Set the color to c, using the local system convention for numbering
  1793. X * colors or video attributes.
  1794. X *
  1795. X * If you implement this, remember to note the original color in
  1796. X * windinit(), before you do any setcolor() commands, and
  1797. X * do a setcolor() back to the original as part of windexit().
  1798. X */
  1799. X  int c:
  1800. X{
  1801. X}
  1802. X
  1803. X
  1804. Xsetrows (r)
  1805. X/*
  1806. X * Set the number of lines to r, if possible.  Otherwise
  1807. X * "do the right thing".  Return the number of lines actually set.
  1808. X *
  1809. X * If you implement this, remember to note the original number of rows
  1810. X * in windinit(), before you do any setrows() commands, and
  1811. X * do a setrows() back to the original as part of windexit().
  1812. X */
  1813. X  int r;
  1814. X{
  1815. X    /* Since we do nothing, just return the current number of lines */
  1816. X    return ( P(P_LI) );
  1817. X}
  1818. X
  1819. X
  1820. Xvbeep ()
  1821. X/*
  1822. X * Do a "visual bell".  This generally consists of flashing the screen
  1823. X * once in inverse video.
  1824. X */
  1825. X{
  1826. X    int    color, revco;
  1827. X
  1828. X    color = P( P_CO );        /* get current color */
  1829. X    revco = reverse_color (color);    /* system-specific */
  1830. X    setcolor (revco);
  1831. X    flushbuf ();
  1832. X    pause ();
  1833. X    setcolor (color);
  1834. X    windgoto (Cursrow, Curscol);
  1835. X    flushbuf ();
  1836. X}
  1837. X
  1838. Xreverse_color (co)
  1839. X/*
  1840. X * Returns the inverse video attribute or color of co.
  1841. X * The existing code below is VERY simple-minded.
  1842. X * Replace it with proper code for your system.
  1843. X */
  1844. X int co;
  1845. X{
  1846. X    if (co)        return (0);
  1847. X    else        return (1);
  1848. X}
  1849. X
  1850. X
  1851. X/********** End of do-it-yourself kit **********************/
  1852. X
  1853. !EOR!
  1854. echo extracting - unix.c
  1855. sed 's/^X//' > unix.c << '!EOR!'
  1856. X/* $Header: /nw/tony/src/stevie/src/RCS/unix.c,v 1.8 89/08/06 09:51:13 tony Exp $
  1857. X *
  1858. X * System-dependent routines for UNIX System V or Berkeley.
  1859. X */
  1860. X
  1861. X#include "stevie.h"
  1862. X#ifdef BSD
  1863. X#include <sgtty.h>
  1864. X#else
  1865. X#include <termio.h>
  1866. X#endif
  1867. X#include <signal.h>
  1868. X
  1869. X/*
  1870. X * inchar() - get a character from the keyboard
  1871. X */
  1872. Xint
  1873. Xinchar()
  1874. X{
  1875. X    char    c;
  1876. X
  1877. X    flushbuf();        /* flush any pending output */
  1878. X
  1879. X    do {
  1880. X        while (read(0, &c, 1) != 1)
  1881. X            ;
  1882. X    } while (c == NUL);
  1883. X
  1884. X    got_int = FALSE;
  1885. X    return c;
  1886. X}
  1887. X
  1888. X#define    BSIZE    2048
  1889. Xstatic    char    outbuf[BSIZE];
  1890. Xstatic    int    bpos = 0;
  1891. X
  1892. Xvoid
  1893. Xflushbuf()
  1894. X{
  1895. X    if (bpos != 0)
  1896. X        write(1, outbuf, bpos);
  1897. X    bpos = 0;
  1898. X}
  1899. X
  1900. X/*
  1901. X * Macro to output a character. Used within this file for speed.
  1902. X */
  1903. X#define    outone(c)    outbuf[bpos++] = c; if (bpos >= BSIZE) flushbuf()
  1904. X
  1905. X/*
  1906. X * Function version for use outside this file.
  1907. X */
  1908. Xvoid
  1909. Xoutchar(c)
  1910. Xchar    c;
  1911. X{
  1912. X    outone(c);
  1913. X}
  1914. X
  1915. Xvoid
  1916. Xoutstr(s)
  1917. Xregister char    *s;
  1918. X{
  1919. X    while (*s) {
  1920. X        outone(*s++);
  1921. X    }
  1922. X}
  1923. X
  1924. Xvoid
  1925. Xbeep()
  1926. X{
  1927. X    if ( P(P_VB) )
  1928. X        vbeep ();
  1929. X    else
  1930. X        outone('\007');
  1931. X}
  1932. X
  1933. X/*
  1934. X * remove(file) - remove a file
  1935. X */
  1936. Xvoid
  1937. Xremove(file)
  1938. Xchar *file;
  1939. X{
  1940. X    unlink(file);
  1941. X}
  1942. X
  1943. X/*
  1944. X * rename(of, nf) - rename existing file 'of' to 'nf'
  1945. X */
  1946. Xvoid
  1947. Xrename(of, nf)
  1948. Xchar    *of, *nf;
  1949. X{
  1950. X    unlink(nf);
  1951. X    link(of, nf);
  1952. X    unlink(of);
  1953. X}
  1954. X
  1955. Xvoid
  1956. Xpause()
  1957. X{
  1958. X    sleep (1);
  1959. X}
  1960. X
  1961. X#ifdef BSD
  1962. Xstatic    struct    sgttyb    ostate;
  1963. X#else
  1964. Xstatic    struct    termio    ostate;
  1965. X#endif
  1966. X
  1967. X/*
  1968. X * Go into cbreak mode
  1969. X */
  1970. Xvoid
  1971. Xset_tty()
  1972. X{
  1973. X#ifdef BSD
  1974. X    struct    sgttyb    nstate;
  1975. X
  1976. X    ioctl(0, TIOCGETP, &ostate);
  1977. X    nstate = ostate;
  1978. X    nstate.sg_flags &= ~(XTABS|CRMOD|ECHO);
  1979. X    nstate.sg_flags |= CBREAK;
  1980. X    ioctl(0, TIOCSETN, &nstate);
  1981. X#else
  1982. X    struct    termio    nstate;
  1983. X
  1984. X    ioctl(0, TCGETA, &ostate);
  1985. X    nstate = ostate;
  1986. X    nstate.c_lflag &= ~(ICANON|ECHO|ECHOE|ECHOK|ECHONL);
  1987. X    nstate.c_cc[VMIN] = 1;
  1988. X    nstate.c_cc[VTIME] = 0;
  1989. X    ioctl(0, TCSETAW, &nstate);
  1990. X#endif
  1991. X}
  1992. X
  1993. X/*
  1994. X * Restore original terminal modes
  1995. X */
  1996. Xvoid
  1997. Xreset_tty()
  1998. X{
  1999. X#ifdef BSD
  2000. X    ioctl(0, TIOCSETP, &ostate);
  2001. X#else
  2002. X    ioctl(0, TCSETAW, &ostate);
  2003. X#endif
  2004. X}
  2005. X
  2006. Xvoid
  2007. Xsig()
  2008. X{
  2009. X    signal(SIGINT, sig);
  2010. X    signal(SIGQUIT, sig);
  2011. X
  2012. X    got_int = TRUE;
  2013. X}
  2014. X
  2015. Xvoid
  2016. Xwindinit()
  2017. X{
  2018. X#ifdef    TERMCAP
  2019. X    if (t_init() != 1) {
  2020. X        fprintf(stderr, "unknown terminal type\n");
  2021. X        exit(1);
  2022. X    }
  2023. X#else
  2024. X    Columns = 80;
  2025. X    P(P_LI) = Rows = 24;
  2026. X#endif
  2027. X
  2028. X    /*
  2029. X     * The code here makes sure that there isn't a window during which
  2030. X     * we could get interrupted and exit with the tty in a weird state.
  2031. X     */
  2032. X    signal(SIGINT, sig);
  2033. X    signal(SIGQUIT, sig);
  2034. X
  2035. X    set_tty();
  2036. X
  2037. X    if (got_int)
  2038. X        windexit(0);
  2039. X}
  2040. X
  2041. Xvoid
  2042. Xwindexit(r)
  2043. Xint r;
  2044. X{
  2045. X    reset_tty();
  2046. X    exit(r);
  2047. X}
  2048. X
  2049. Xvoid
  2050. Xwindgoto(r, c)
  2051. Xregister int    r, c;
  2052. X{
  2053. X#ifdef    TERMCAP
  2054. X    char    *tgoto();
  2055. X#else
  2056. X    r += 1;
  2057. X    c += 1;
  2058. X#endif
  2059. X
  2060. X    /*
  2061. X     * Check for overflow once, to save time.
  2062. X     */
  2063. X    if (bpos + 8 >= BSIZE)
  2064. X        flushbuf();
  2065. X
  2066. X#ifdef    TERMCAP
  2067. X    outstr(tgoto(T_CM, c, r));
  2068. X#else
  2069. X    outbuf[bpos++] = '\033';
  2070. X    outbuf[bpos++] = '[';
  2071. X    if (r >= 10)
  2072. X        outbuf[bpos++] = r/10 + '0';
  2073. X    outbuf[bpos++] = r%10 + '0';
  2074. X    outbuf[bpos++] = ';';
  2075. X    if (c >= 10)
  2076. X        outbuf[bpos++] = c/10 + '0';
  2077. X    outbuf[bpos++] = c%10 + '0';
  2078. X    outbuf[bpos++] = 'H';
  2079. X#endif
  2080. X}
  2081. X
  2082. XFILE *
  2083. Xfopenb(fname, mode)
  2084. Xchar    *fname;
  2085. Xchar    *mode;
  2086. X{
  2087. X    return fopen(fname, mode);
  2088. X}
  2089. X
  2090. Xchar *
  2091. Xfixname(s)
  2092. Xchar    *s;
  2093. X{
  2094. X    return s;
  2095. X}
  2096. X
  2097. X/*
  2098. X * doshell() - run a command or an interactive shell
  2099. X */
  2100. Xvoid
  2101. Xdoshell(cmd)
  2102. Xchar    *cmd;
  2103. X{
  2104. X    char    *getenv();
  2105. X    char    cline[128];
  2106. X
  2107. X    outstr("\r\n");
  2108. X    flushbuf();
  2109. X
  2110. X    if (cmd == NULL) {
  2111. X        if ((cmd = getenv("SHELL")) == NULL)
  2112. X            cmd = "/bin/sh";
  2113. X        sprintf(cline, "%s -i", cmd);
  2114. X        cmd = cline;
  2115. X    }
  2116. X
  2117. X    reset_tty();
  2118. X    system(cmd);
  2119. X    set_tty();
  2120. X
  2121. X    wait_return();
  2122. X}
  2123. X
  2124. X
  2125. X/*
  2126. X *    FILL IT IN, FOR YOUR SYSTEM, AND SHARE IT!
  2127. X *
  2128. X *    The next couple of functions do system-specific stuff.
  2129. X *    They currently do nothing; I'm not familiar enough with
  2130. X *    system-specific programming on this system.
  2131. X *    If you fill it in for your system, please post the results
  2132. X *    and share with the rest of us.
  2133. X */
  2134. X
  2135. X
  2136. Xsetcolor (c)
  2137. X/*
  2138. X * Set the color to c, using the local system convention for numbering
  2139. X * colors or video attributes.
  2140. X *
  2141. X * If you implement this, remember to note the original color in
  2142. X * windinit(), before you do any setcolor() commands, and
  2143. X * do a setcolor() back to the original as part of windexit().
  2144. X */
  2145. X  int c;
  2146. X{
  2147. X    /* Dummy routine, just return 0 */
  2148. X    return (0);
  2149. X}
  2150. X
  2151. X
  2152. Xsetrows (r)
  2153. X/*
  2154. X * Set the number of lines to r, if possible.  Otherwise
  2155. X * "do the right thing".  Return the number of lines actually set.
  2156. X *
  2157. X * If you implement this, remember to note the original number of rows
  2158. X * in windinit(), before you do any setrows() commands, and
  2159. X * do a setrows() back to the original as part of windexit().
  2160. X */
  2161. X  int r;
  2162. X{
  2163. X    /* Since we do nothing, just return the current number of lines */
  2164. X    return ( P(P_LI) );
  2165. X}
  2166. X
  2167. X
  2168. Xvbeep ()
  2169. X/*
  2170. X * Do a "visual bell".  This generally consists of flashing the screen
  2171. X * once in inverse video.
  2172. X */
  2173. X{
  2174. X    int    color, revco;
  2175. X
  2176. X    color = P( P_CO );        /* get current color */
  2177. X    revco = reverse_color (color);    /* system-specific */
  2178. X    setcolor (revco);
  2179. X    flushbuf ();
  2180. X    pause ();
  2181. X    setcolor (color);
  2182. X    windgoto (Cursrow, Curscol);
  2183. X    flushbuf ();
  2184. X}
  2185. X
  2186. Xreverse_color (co)
  2187. X/*
  2188. X * Returns the inverse video attribute or color of co.
  2189. X * The existing code below is VERY simple-minded.
  2190. X * Replace it with proper code for your system.
  2191. X */
  2192. X int co;
  2193. X{
  2194. X    if (co)        return (0);
  2195. X    else        return (1);
  2196. X}
  2197. X
  2198. X
  2199. X/********** End of do-it-yourself kit **********************/
  2200. !EOR!
  2201. echo extracting - setenv.c
  2202. sed 's/^X//' > setenv.c << '!EOR!'
  2203. X/*****************************************************************************
  2204. X * A program for adding or changing environment variable values for MSDOS.
  2205. X * The "set" command provided by command.com is very limited.  It fails to
  2206. X * provide the ability to use quotation marks and escape characters and
  2207. X * octal/hex constants in the value definition.  Setenv provides these
  2208. X * abilities.
  2209. X *
  2210. X * Usage notes:
  2211. X *
  2212. X *    setenv <symbol> = <value>
  2213. X *
  2214. X *    <symbol> ::= legal MSDOS environment symbol.  Lower case converted
  2215. X *             to uppercase.
  2216. X *
  2217. X *    <value>  ::= environment symbol value in one of three forms:
  2218. X *
  2219. X *             * No quotation marks.  The value is the literal string
  2220. X *               of characters starting IMMEDIATELY after the equal
  2221. X *               sign and extending to the end-of-line.
  2222. X *
  2223. X *             * Single quotation marks (').  The value is the literal
  2224. X *               string enclosed in quotation marks.
  2225. X *
  2226. X *             * Double quotation marks (").  The value is the string
  2227. X *               enclosed in double quotation marks.  Backslash escape
  2228. X *               constructions are processed -- this includes the usual
  2229. X *               C language constructions such as \n for newline and
  2230. X *               \r for carriage return plus octal and hexadecimal
  2231. X *               constants (\ddd & \0xdd, respectively).
  2232. X *****************************************************************************/
  2233. X
  2234. X/*****************************************************************************
  2235. X * Based on a program by Alan J Myrvold (ajmyrvold@violet.waterloo.edu)
  2236. X *
  2237. X * WARNING WARNING WARNING - virtually no error checking is done !!
  2238. X *                           use at own risk !!
  2239. X *
  2240. X * This program by Larry A. Shurr (las@cbema.ATT.COM)
  2241. X *
  2242. X * I added checking for env seg overrun, so now it's a little more robust.
  2243. X *****************************************************************************/
  2244. X
  2245. X/*****************************************************************************
  2246. X *
  2247. X * Notes by Alan J Myrgold:
  2248. X *
  2249. X * Technical information : A program's PSP contains a pointer at
  2250. X * offset 44 (decimal) to a COPY of the parent's environment.
  2251. X * The environment is a set of strings of the form NAME=value,
  2252. X * each terminated by a NULL byte.
  2253. X * An additional NULL byte marks the end of the environment.
  2254. X * The environment area is ALWAYS paragraph aligned
  2255. X * i.e. on a 16 byte boundary.
  2256. X *
  2257. X * Searching backwards from the PSP, I consistently find
  2258. X * two copies of the envronment area.
  2259. X *
  2260. X * The program : finds the two areas
  2261. X *               reads one into memory
  2262. X *               udpates the specified environment variable
  2263. X *               writes updated environment to parent environment
  2264. X *****************************************************************************/
  2265. X
  2266. X#include <stdio.h>
  2267. X#include <stdlib.h>
  2268. X#include <string.h>
  2269. X#include <time.h>
  2270. X#include <process.h>
  2271. X#include <conio.h>
  2272. X#include <dos.h>
  2273. X
  2274. X#define FALSE 0
  2275. X#define TRUE  1
  2276. X
  2277. Xstruct mcb {                /* MSDOS Memory Control Block */
  2278. X  unsigned char tag4D;            /* Tag field must = 0x4D */
  2279. X  unsigned int  next;            /* Segment base for next block */
  2280. X  unsigned int  size;            /* Memory block size in paragraphs */
  2281. X};
  2282. X
  2283. X
  2284. Xunsigned env_size = 0;            /* Maintain size of environment */
  2285. X/***************************************************************************/
  2286. Xint env_size_bytes(unsigned env_seg)
  2287. X/* Determine the length of the environment area in bytes */
  2288. X{
  2289. X    int n;
  2290. X
  2291. X    n = 0;
  2292. X    while (peekb(env_seg,n) != 0) {
  2293. X          while (peekb(env_seg,n) != 0) n++;
  2294. X          n++;
  2295. X    }
  2296. X    return(n);
  2297. X}
  2298. X/***************************************************************************/
  2299. Xint env_size_strings(unsigned env_seg)
  2300. X/* Determine how many strings are in the environment area */
  2301. X{
  2302. X    int k,n;
  2303. X
  2304. X    k = n = 0;
  2305. X    while (peekb(env_seg,n) != 0) {
  2306. X          k++;
  2307. X          while (peekb(env_seg,n) != 0) n++;
  2308. X          n++;
  2309. X    }
  2310. X    return(k);
  2311. X}
  2312. X/***************************************************************************/
  2313. Xint peek_cmp(unsigned seg1,unsigned seg2,int nbytes)
  2314. X/* A trivial compare routine for segement aligned data items */
  2315. X{
  2316. X   int i;
  2317. X
  2318. X   for (i = 0; (i < nbytes) && (peekb(seg1,i) == peekb(seg2,i)); i++);
  2319. X   return(i == nbytes);
  2320. X}
  2321. X/***************************************************************************/
  2322. Xvoid find_env(unsigned seg_ray[2])
  2323. X{
  2324. X    unsigned psp_seg,copy_of_seg,env_seg;
  2325. X    int k,n;
  2326. X
  2327. X/* Find first copy of environment */
  2328. X    psp_seg = _psp;
  2329. X    copy_of_seg = peek(psp_seg,44);
  2330. X
  2331. X/* Set return value to non-garabage */
  2332. X    seg_ray[0] = seg_ray[1] = copy_of_seg;
  2333. X
  2334. X/* Search back to find 2 copies of environment */
  2335. X    env_size = n = env_size_bytes(copy_of_seg);
  2336. X    env_seg = copy_of_seg - 1;
  2337. X    for (k = 0; (env_seg != 0) && (k < 2); k++) {
  2338. X          while ((env_seg != 0) &&
  2339. X                 (peek_cmp(copy_of_seg,env_seg,n) == 0)) {
  2340. X                     env_seg--;
  2341. X          }
  2342. X          if (env_seg != 0) {
  2343. X              seg_ray[k] = env_seg;
  2344. X              env_seg--;
  2345. X          }
  2346. X    }
  2347. X
  2348. X/* If not found, display error message and abort */
  2349. X    if (k != 2) {
  2350. X       fprintf(stderr,"Two copies of the environment were not found\n");
  2351. X       exit(-1);
  2352. X    }
  2353. X}
  2354. X/***************************************************************************/
  2355. Xvoid read_env(unsigned env_seg,int *k,char ***s,char ***t)
  2356. X/* Read environment into a malloc'd array of malloc'd strings */
  2357. X{
  2358. X  int i,j,n;
  2359. X
  2360. X  env_size = env_size_bytes(env_seg);
  2361. X
  2362. X  *k = env_size_strings(env_seg);
  2363. X  *s = (char **) malloc((*k)*sizeof(char *));
  2364. X  *t = (char **) malloc((*k)*sizeof(char *));
  2365. X
  2366. X  n = 0;
  2367. X  for (i = 0; i < *k; i++) {
  2368. X    for (j = 0; peekb(env_seg,n+j) != '='; j++);
  2369. X    (*s)[i] = (char *) malloc(j+1);
  2370. X    for (j = 0; peekb(env_seg,n+j) != '='; j++)
  2371. X      ((*s)[i])[j] = peekb(env_seg,n+j);
  2372. X    ((*s)[i])[j] = 0;
  2373. X    n += j + 1;
  2374. X    for (j = 0; peekb(env_seg,n+j) != 0; j++);
  2375. X    (*t)[i] = (char *) malloc(j+1);
  2376. X    for (j = 0; peekb(env_seg,n+j) != 0; j++)
  2377. X      ((*t)[i])[j] = peekb(env_seg,n+j);
  2378. X    ((*t)[i])[j] = 0;
  2379. X    n += j + 1;
  2380. X  }
  2381. X}
  2382. X/***************************************************************************/
  2383. Xvoid write_env(unsigned env_seg, int k, char **s, char **t)
  2384. X/* Write the environment back out to memory */
  2385. X{
  2386. X  int i,j,n;
  2387. X
  2388. X  struct mcb far *tmcb = (struct mcb far *)((long)(env_seg-1) << 16);
  2389. X
  2390. X  if (tmcb->tag4D == 0x4D) {
  2391. X    unsigned env_seg_siz = tmcb->size << 4;
  2392. X    if (env_size < env_seg_siz) {
  2393. X      for (n = i = 0; i < k; i++) {
  2394. X        char *si = s[i];
  2395. X        char *ti = t[i];
  2396. X    for (j = 0; si[j] != 0; j++) pokeb(env_seg,n++,si[j]);
  2397. X    pokeb(env_seg,n++,'=');
  2398. X    for (j = 0; ti[j] != 0; j++) pokeb(env_seg,n++,ti[j]);
  2399. X    pokeb(env_seg,n++,0);
  2400. X      }
  2401. X      pokeb(env_seg,n,0);
  2402. X    } else {
  2403. X      fprintf(stderr,"Insufficient space in environment\n");
  2404. X      exit(-1);
  2405. X    }
  2406. X  } else {
  2407. X    fprintf(stderr,"Environment memory control block trashed\n");
  2408. X    exit(-1);
  2409. X  }
  2410. X}
  2411. X/***************************************************************************/
  2412. Xchar *get_env_var(int k,char **s,char **t,char *var)
  2413. X/* Return the value of the environment variable or NULL if not found */
  2414. X{
  2415. X    char *val;
  2416. X    int i;
  2417. X
  2418. X    val = NULL;
  2419. X    for (i = 0; i < k; i++) if (stricmp(s[i],var) == 0) val = t[i];
  2420. X
  2421. X    return(val);
  2422. X}
  2423. X
  2424. X/***************************************************************************/
  2425. Xvoid set_env_var(int *k,char ***s,char ***t,char *var,char *val)
  2426. X/* Set a new or existing environment variable to a new value */
  2427. X{
  2428. X  int i,done;
  2429. X
  2430. X  done = 0;
  2431. X  for (i = 0; i < *k; i++) {
  2432. X    if (stricmp((*s)[i],var) == 0) {
  2433. X      /* Existing variable */
  2434. X      done = 1;
  2435. X      env_size -= strlen((*t)[i]);
  2436. X      free((*t)[i]);
  2437. X      (*t)[i] = (char *) malloc(1+strlen(val));
  2438. X      strcpy((*t)[i],val);
  2439. X      env_size += strlen((*t)[i]);
  2440. X    }
  2441. X  }
  2442. X
  2443. X  if (!done) {
  2444. X    /* New environment variable */
  2445. X    (*k)++;
  2446. X    *s = realloc(*s,(*k)*sizeof(char *));
  2447. X    *t = realloc(*t,(*k)*sizeof(char *));
  2448. X    (*s)[*k-1] = (char *) malloc(1+strlen(var));
  2449. X    strcpy((*s)[*k-1],var);
  2450. X    strupr((*s)[*k-1]);
  2451. X    (*t)[*k-1] = (char *) malloc(1+strlen(val));
  2452. X    strcpy((*t)[*k-1],val);
  2453. X    /* Length of name  + length of '=' + length of value + length of '\0' */
  2454. X    env_size += (strlen((*s)[*k-1]) + 1 + strlen((*t)[*k-1]) + 1);
  2455. X  }
  2456. X}
  2457. X/***************************************************************************/
  2458. Xvoid show_env(int k,char **s,char **t)
  2459. X/* Display the array of environment strings */
  2460. X{
  2461. X   int i;
  2462. X   for (i = 0; i < k; i++) printf("%s=%s\n",s[i],t[i]);
  2463. X}
  2464. X/***************************************************************************/
  2465. Xvoid get_cmdline(char *cmd)
  2466. X/* Read raw command line text into string buffer */
  2467. X{
  2468. X    char far *pcmd;
  2469. X
  2470. X    int idx,odx;
  2471. X
  2472. X    pcmd = (char far *)((long)_psp << 16) + 128L;
  2473. X
  2474. X    for (idx = *pcmd++, odx = 0; idx > 0; idx--, odx++) {
  2475. X      cmd[odx] = *pcmd++;
  2476. X    }
  2477. X
  2478. X    cmd[odx] = '\0';
  2479. X}
  2480. X/***************************************************************************/
  2481. Xchar_in(char ch, char *set)
  2482. X/* Determine if a character is in a set of characters */
  2483. X{
  2484. X  do {
  2485. X    if (ch == *set) return(TRUE);
  2486. X  } while ((int)*(++set));
  2487. X  return(FALSE);
  2488. X}
  2489. X/***************************************************************************/
  2490. Xchar get_num(char *cmd, int *pidx)
  2491. X/* Interpret octal or hexadecimal constant in string */
  2492. X{
  2493. X  int   accum  = 0;
  2494. X  char  ch;
  2495. X  int   f_scan = TRUE;
  2496. X  int   idx    = *pidx;
  2497. X  int   limit;
  2498. X  char *nch    = cmd+idx;
  2499. X  char *och    = nch+1;
  2500. X  int   radix;
  2501. X
  2502. X#define HEXDIG "0123456789ABCDEFabcdef"
  2503. X
  2504. X  if (*nch == '0' && char_in(*och,"xX") && char_in(*(och+1),HEXDIG)) {
  2505. X    radix = 16;
  2506. X    limit = 2;
  2507. X    och += 1;
  2508. X  } else {
  2509. X    radix = 8;
  2510. X    limit = 3;
  2511. X    och = nch;
  2512. X  }
  2513. X
  2514. X  while (limit-- > 0 && f_scan) {
  2515. X
  2516. X    f_scan = FALSE;
  2517. X
  2518. X    while ((int)(*nch)) *nch++ = *och++;
  2519. X
  2520. X    nch = cmd+idx;
  2521. X    och = nch+1;
  2522. X
  2523. X    switch (ch = *nch) {
  2524. X      case '0' :
  2525. X      case '1' :
  2526. X      case '2' :
  2527. X      case '3' :
  2528. X      case '4' :
  2529. X      case '5' :
  2530. X      case '6' :
  2531. X      case '7' :
  2532. X      case '8' :
  2533. X      case '9' :
  2534. X    if (ch == 9 && radix == 8) break;
  2535. X    accum = accum * radix + (int)(ch - '0');
  2536. X        f_scan = TRUE;
  2537. X    break;
  2538. X      case 'A' :
  2539. X      case 'B' :
  2540. X      case 'C' :
  2541. X      case 'D' :
  2542. X      case 'E' :
  2543. X      case 'F' :
  2544. X    if (radix == 8) break;
  2545. X    accum = accum * radix + (int)(ch - 'A') + 10;
  2546. X        f_scan = TRUE;
  2547. X    break;
  2548. X      case 'a' :
  2549. X      case 'b' :
  2550. X      case 'c' :
  2551. X      case 'd' :
  2552. X      case 'e' :
  2553. X      case 'f' :
  2554. X    if (radix == 8) break;
  2555. X    accum = accum * radix + (int)(ch - 'a') + 10;
  2556. X        f_scan = TRUE;
  2557. X    break;
  2558. X      default  : break;
  2559. X    }
  2560. X  }
  2561. X
  2562. X  *pidx = idx;
  2563. X  return(accum);
  2564. X}
  2565. X/***************************************************************************/
  2566. Xget_escape(char *cmd, int *pidx, char quote)
  2567. X/* Interpret escape'd (i.e., '\' (backslash) character */
  2568. X{
  2569. X  int   idx = *pidx;
  2570. X
  2571. X  if (quote == '"') {
  2572. X    char *nch = cmd+idx;
  2573. X    char *och = nch+1;
  2574. X    char *xch = nch;
  2575. X    while ((int)(*nch)) *nch++ = *och++;
  2576. X    switch (*xch) {
  2577. X      case 'a' : *xch = '\a'; break;
  2578. X      case 'b' : *xch = '\b'; break;
  2579. X      case 'c' : *xch = '\c'; break;
  2580. X      case 'd' : *xch = '\d'; break;
  2581. X      case 'e' : *xch = '\e'; break;
  2582. X      case 'f' : *xch = '\f'; break;
  2583. X      case 'g' : *xch = '\g'; break;
  2584. X      case 'h' : *xch = '\h'; break;
  2585. X      case 'i' : *xch = '\i'; break;
  2586. X      case 'j' : *xch = '\j'; break;
  2587. X      case 'k' : *xch = '\k'; break;
  2588. X      case 'l' : *xch = '\l'; break;
  2589. X      case 'm' : *xch = '\m'; break;
  2590. X      case 'n' : *xch = '\n'; break;
  2591. X      case 'o' : *xch = '\o'; break;
  2592. X      case 'p' : *xch = '\p'; break;
  2593. X      case 'q' : *xch = '\q'; break;
  2594. X      case 'r' : *xch = '\r'; break;
  2595. X      case 's' : *xch = '\s'; break;
  2596. X      case 't' : *xch = '\t'; break;
  2597. X      case 'u' : *xch = '\u'; break;
  2598. X      case 'v' : *xch = '\v'; break;
  2599. X      case 'w' : *xch = '\w'; break;
  2600. X      case 'x' : *xch = '\x'; break;
  2601. X      case 'y' : *xch = '\y'; break;
  2602. X      case 'z' : *xch = '\z'; break;
  2603. X      case '0' :
  2604. X      case '1' :
  2605. X      case '2' :
  2606. X        *xch = get_num(cmd, &idx);
  2607. X        break;
  2608. X    }
  2609. X  }
  2610. X
  2611. X  *pidx = idx + 1;
  2612. X}
  2613. X/***************************************************************************/
  2614. Xget_qvalue(char *cmd, int idx, char quote, char **value)
  2615. X/* Extract a quoted value part from command line */
  2616. X{
  2617. X  char ch;
  2618. X  int  f_esc;
  2619. X
  2620. X  *value = cmd + (++idx);
  2621. X
  2622. X  do {
  2623. X    while ((int)(ch = cmd[idx]) && ch != '\\' && ch != quote) idx++;
  2624. X    if (!(int)ch) return(-1);
  2625. X    if (ch == '\\') {
  2626. X      f_esc = TRUE;
  2627. X      get_escape(cmd, &idx, quote);
  2628. X    } else f_esc = FALSE;
  2629. X  } while (f_esc);
  2630. X
  2631. X  cmd[idx] = '\0';
  2632. X
  2633. X  for (idx += 1; (int)(ch = cmd[idx]) && ch == ' '; idx++);
  2634. X
  2635. X  if ((int)ch) return(-1);
  2636. X
  2637. X  return(0);
  2638. X}
  2639. X/***************************************************************************/
  2640. Xget_parm(char **name, char **value)
  2641. X/* Extract environment symbol name and value from command line */
  2642. X{
  2643. X    char ch;
  2644. X    int  idx;
  2645. X    int  sdx;
  2646. X
  2647. X    static char cmd[128];
  2648. X
  2649. X    get_cmdline(cmd);
  2650. X
  2651. X    for (idx = 0; (int)(ch = cmd[idx]) && ch  == ' '; idx++);
  2652. X
  2653. X    if (!(int)ch) return(1);
  2654. X
  2655. X    *name = cmd + idx;
  2656. X
  2657. X    for (; (int)(ch = cmd[idx]) && ch != '=' && ch != ' '; idx++);
  2658. X
  2659. X    if (!(int)ch) return(-1);
  2660. X
  2661. X    if (ch == ' ') {
  2662. X      cmd[idx] = '\0';
  2663. X      for (idx += 1; (int)(ch = cmd[idx]) && ch != '='; idx++);
  2664. X    } else cmd[idx] = '\0';
  2665. X
  2666. X    if (!(int)ch) return(-1);
  2667. X
  2668. X    for (sdx = (idx += 1); (int)(ch = cmd[idx]) && ch == ' '; idx++);
  2669. X
  2670. X    /*if (!(int)ch) return(-1);*/
  2671. X
  2672. X    switch (ch) {
  2673. X      case '"'  : return(get_qvalue(cmd, idx, '"', value));
  2674. X      case '\'' : return(get_qvalue(cmd, idx, '\'', value));
  2675. X      default   : *value = cmd + sdx; break;
  2676. X    }
  2677. X
  2678. X    return(0);
  2679. X}
  2680. X/***************************************************************************/
  2681. Xmain(int argc,char **argv)
  2682. X{
  2683. X    unsigned env_seg[2];
  2684. X    char **s,**t;
  2685. X    int k;
  2686. X    long now;
  2687. X    struct tm *local;
  2688. X
  2689. X    static char *name = NULL, *value = NULL;
  2690. X
  2691. X    switch (get_parm(&name,&value)) {
  2692. X
  2693. X    case -1:
  2694. X
  2695. X    fprintf(stderr,"Invalid symbol definition syntax\n");
  2696. X    exit(-1);
  2697. X
  2698. X    case 0:
  2699. X
  2700. X        /* Find and read environment */
  2701. X
  2702. X        find_env(env_seg);
  2703. X        read_env(env_seg[1],&k,&s,&t);
  2704. X
  2705. X    /* Set the variable <name> to <value> */
  2706. X
  2707. X    set_env_var(&k,&s,&t,name,value);
  2708. X
  2709. X    /* Update caller's environment */
  2710. X
  2711. X    write_env(env_seg[0],k,s,t);
  2712. X
  2713. X    break;
  2714. X
  2715. X    case 1:
  2716. X
  2717. X    fprintf(stderr,"Usage: setenv <symbol name> = <value>\n");
  2718. X    break;
  2719. X    }
  2720. X
  2721. X    return(0);
  2722. X}
  2723. X/***************************************************************************/
  2724. X
  2725. !EOR!
  2726. echo extracting - ctags.c
  2727. sed 's/^X//' > ctags.c << '!EOR!'
  2728. X/*
  2729. X * ctags - first cut at a UNIX ctags re-implementation
  2730. X */
  2731. X
  2732. X/*
  2733. X * Caveats:
  2734. X *
  2735. X * Only simple function declarations are recognized, as in:
  2736. X *
  2737. X * type
  2738. X * fname(...)
  2739. X *
  2740. X * where "fname" is the name of the function and must come at the beginning
  2741. X * of a line. This is the form I always use, so the limitation doesn't
  2742. X * bother me.
  2743. X *
  2744. X * Macros (with or without parameters) of the following form are also detected:
  2745. X *
  2746. X * "#" [white space] "define" [white space] NAME
  2747. X *
  2748. X * No sorting or detection of duplicate functions is done.
  2749. X *
  2750. X * If there are no arguments, a list of filenames to be searched is read
  2751. X * from the standard input. Otherwise, all arguments are assumed to be
  2752. X * file names.
  2753. X *
  2754. X * Tony Andrews
  2755. X * August 1987
  2756. X */
  2757. X
  2758. X#include <stdio.h>
  2759. X#include <ctype.h>
  2760. X#include <string.h>
  2761. X
  2762. Xint    ac;
  2763. Xchar    **av;
  2764. X
  2765. Xmain(argc, argv)
  2766. Xint    argc;
  2767. Xchar    *argv[];
  2768. X{
  2769. X    char    *fname, *nextfile();
  2770. X    FILE    *tp, *fopen();
  2771. X
  2772. X    ac = argc;
  2773. X    av = argv;
  2774. X
  2775. X    if ((tp = fopen("tags", "w")) == NULL) {
  2776. X        fprintf(stderr, "Can't create tags file\n");
  2777. X        exit(1);
  2778. X    }
  2779. X
  2780. X    while ((fname = nextfile()) != NULL)
  2781. X        dofile(fname, tp);
  2782. X
  2783. X    fclose(tp);
  2784. X    exit(0);
  2785. X}
  2786. X
  2787. Xchar *
  2788. Xnextfile()    /* returns ptr to next file to be searched, null at end */
  2789. X{
  2790. X    static    char    buf[128];
  2791. X    static    int    ap = 1;
  2792. X    char    *gets();
  2793. X
  2794. X    if (ac <= 1) {        /* read from stdin */
  2795. X        if (feof(stdin))
  2796. X            return (char *) NULL;
  2797. X        return (gets(buf));
  2798. X    } else {
  2799. X        if (ap < ac)
  2800. X            return av[ap++];
  2801. X        else
  2802. X            return (char *) NULL;
  2803. X    }
  2804. X}
  2805. X
  2806. X#define    LSIZE    512    /* max. size of a line */
  2807. X
  2808. X#define    BEGID(c)    (isalpha(c) || (c) == '_')
  2809. X#define    MIDID(c)    (isalpha(c) || isdigit(c) || (c) == '_')
  2810. X
  2811. Xdofile(fn, tp)
  2812. Xchar    *fn;
  2813. XFILE    *tp;
  2814. X{
  2815. X    FILE    *fp, *fopen();
  2816. X    char    *cp, *strchr();
  2817. X    char    lbuf[LSIZE];
  2818. X    char    func[LSIZE];
  2819. X    int    i, j;
  2820. X
  2821. X    if ((fp = fopen(fn, "r")) == NULL) {
  2822. X        fprintf(stderr, "Can't open file '%s' - skipping\n", fn);
  2823. X        return;
  2824. X    }
  2825. X
  2826. X    while (fgets(lbuf, LSIZE, fp) != NULL) {
  2827. X
  2828. X        lbuf[strlen(lbuf)-1] = '\0';    /* bag the newline */
  2829. X
  2830. X        if (BEGID(lbuf[0])) {        /* could be a function */
  2831. X            for (i=0; MIDID(lbuf[i]) ;i++)    /* grab the name */
  2832. X                func[i] = lbuf[i];
  2833. X
  2834. X            func[i] = '\0';        /* null terminate the name */
  2835. X
  2836. X            /*
  2837. X             * We've skipped to the end of what may be a function
  2838. X             * name. Check to see if the next non-whitespace
  2839. X             * char is a paren,
  2840. X             * and make sure the closing paren is here too.
  2841. X             */
  2842. X            while (lbuf[i]==' ' || lbuf[i]=='\t') i++;
  2843. X            if (lbuf[i]=='(' && (((cp = strchr(lbuf,')'))!=NULL))) {
  2844. X                *++cp = '\0';
  2845. X                fprintf(tp, "%s\t%s\t/^%s$/\n", func,fn,lbuf);
  2846. X            }
  2847. X
  2848. X        } else if (lbuf[0] == '#') {    /* could be a define */
  2849. X            for (i=1; isspace(lbuf[i]) ;i++)
  2850. X                ;
  2851. X            if (strncmp(&lbuf[i], "define", 6) != 0)
  2852. X                continue;
  2853. X
  2854. X            i += 6;            /* skip "define" */
  2855. X
  2856. X            for (; isspace(lbuf[i]) ;i++)
  2857. X                ;
  2858. X
  2859. X            if (!BEGID(lbuf[i]))
  2860. X                continue;
  2861. X
  2862. X            for (j=0; MIDID(lbuf[i]) ;i++, j++)
  2863. X                func[j] = lbuf[i];
  2864. X
  2865. X            func[j] = '\0';        /* null terminate the name */
  2866. X            lbuf[i] = '\0';
  2867. X            fprintf(tp, "%s\t%s\t/^%s/\n", func, fn, lbuf);
  2868. X        }
  2869. X    }
  2870. X    fclose(fp);
  2871. X}
  2872. !EOR!
  2873.  
  2874.