home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume7 / crisp1.9 / part31 < prev    next >
Encoding:
Text File  |  1989-06-21  |  49.4 KB  |  2,275 lines

  1. Newsgroups: comp.sources.misc
  2. From: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  3. Subject: v07i051: CRISP release 1.9 part 30/32
  4. Organization: Reuters Ltd PLC, Marlow, England
  5. Reply-To: fox@marlow.UUCP (Paul Fox)
  6.  
  7. Posting-number: Volume 7, Issue 51
  8. Submitted-by: fox@marlow.UUCP (Paul Fox)
  9. Archive-name: crisp1.9/part31
  10.  
  11.  
  12.  
  13. #!/bin/sh
  14. # this is part 10 of a multipart archive
  15. # do not concatenate these parts, unpack them in order with /bin/sh
  16. # file ./tty.c continued
  17. #
  18. CurArch=10
  19. if test ! -r s2_seq_.tmp
  20. then echo "Please unpack part 1 first!"
  21.      exit 1; fi
  22. ( read Scheck
  23.   if test "$Scheck" != $CurArch
  24.   then echo "Please unpack part $Scheck next!"
  25.        exit 1;
  26.   else exit 0; fi
  27. ) < s2_seq_.tmp || exit 1
  28. echo "x - Continuing file ./tty.c"
  29. sed 's/^X//' << 'SHAR_EOF' >> ./tty.c
  30. X    char    *bg[16];
  31. X    } COLORS;
  32. XCOLORS    colors = {
  33. X    {"\033[0;30m", "\033[0;34m", "\033[0;32m", "\033[0;36m", /* Foreground. */
  34. X     "\033[0;31m", "\033[0;35m", "\033[0;33m", "\033[0;37m",
  35. X     "\033[30;1m", "\033[34;1m", "\033[32;1m", "\033[36;1m",
  36. X     "\033[31;1m", "\033[35;1m", "\033[33;1m", "\033[37;1m"},
  37. X    {"\033[40m", "\033[44m", "\033[42m", "\033[46m", /* Background. */
  38. X     "\033[41m", "\033[45m", "\033[43m", "\033[47m",
  39. X     "\033[40;1m", "\033[44;1m", "\033[42;1m", "\033[46;1m",
  40. X     "\033[41;1m", "\033[45;1m", "\033[43;1m", "\033[47;1m"},
  41. X    };
  42. X
  43. Xint     LI;                     /* standard # lines */
  44. Xint    AM;            /* Has auto-margins.        */
  45. Xchar
  46. X    *AL,                    /* add line */
  47. X    *BC,            /* Backspace character. */
  48. X    *CD,            /* Clear to end of display.        */
  49. X    *CE,            /* Clear to end of line. */
  50. X    *CL,            /* Clear screen             */
  51. X    *CM,            /* Cursor motion */
  52. X    *CS,                    /* set scroll region                    */
  53. X    *DC,            /* Delete a character.    */
  54. X    *DL,                    /* del line */
  55. X    *EI,                    /* end insert mode */
  56. X    *HO,            /* Home cursor.        */
  57. X    *IC,                    /* insert a single space */
  58. X    *IM,                    /* insert mode */
  59. X    *IS,            /* Init sequence. */
  60. X    *MB,            /* Turn on blinking.            */
  61. X    *MD,            /* Make bold                 */
  62. X    *ME,            /* Turn off all attributes.        */
  63. X    *RS,            /* Reset sequence.             */
  64. X    *SE,            /* End standout mode.            */
  65. X    *SO,            /* Start standout mode.            */
  66. X    *SR,                    /* back index (used with scroll region  */
  67. X    *TE,                    /* term end --- end using cursor motion */
  68. X    *TI,                    /* term init -- start using cursor motion */
  69. X    *UP,            /* Cursor up.        */
  70. X    *pAL,                   /* parameterized add line */
  71. X    *pDL;                   /* parameterized delete line */
  72. X    
  73. Xchar    *K[NFKEYS];             /* other function key codes             */
  74. Xchar    *KS, *KE;               /* enter keypad mode, exit keypad mode  */
  75. Xint     SG;     /* number of glitches, 0 for invisable, -1 for none     */
  76. Xchar    *termcap_strings = 
  77. X"AL DL al bc cd ce cl cm cs dc dl ei ho ic im is ks ke mb me mr rs se so sr te ti up ";
  78. Xchar    **termcap_ptrs[] = {
  79. X    &pAL, &pDL,
  80. X    &AL, &BC, &CD, &CE, &CL, &CM, &CS, &DC, &DL, &EI, &HO, &IC, 
  81. X    &IM, &IS, &KS, &KE, &MB, &MD, &ME, &RS, &SE, &SO, &SR, &TE, &TI, &UP
  82. X        };
  83. X
  84. X/*
  85. X * Initialize the terminal when the editor
  86. X * gets started up.
  87. X */
  88. Xstatic char tcbuf[TCAPSLEN];
  89. X
  90. Xvoid
  91. Xttinit() 
  92. X{
  93. X    char *ggetenv();
  94. X    char *p, *tgetstr();
  95. X    char *tv_stype;
  96. X    char    *tptr;
  97. X    char    ***cptr;
  98. X    char    *cp;
  99. X
  100. X    if ((tv_stype = ggetenv("TERM")) == NULL)
  101. X        panic("Environment variable TERM not defined!");
  102. X
  103. X    if((tgetent(tcbuf, tv_stype)) != 1) {
  104. X        extern char *termcap_dir;
  105. X        fprintf(stderr, 
  106. X            "Terminal type '%s' not found in %s.\n",
  107. X            tv_stype, termcap_dir);
  108. X        exit(1);
  109. X        }
  110. X
  111. X    p = tcapbuf;
  112. X
  113. X    LI = tgetnum("li");
  114. X    AM = tgetflag("am");
  115. X    SG = tgetnum("sg");
  116. X
  117. X    cptr = termcap_ptrs;
  118. X    for (tptr = termcap_strings; *tptr; tptr += 3) {
  119. X        char    *cp;
  120. X        char    tmpbuf[3];
  121. X        tmpbuf[0] = tptr[0];
  122. X        tmpbuf[1] = tptr[1];
  123. X        tmpbuf[2] = 0;
  124. X        if ((cp = tgetstr(tmpbuf, &p)) && *cp)
  125. X            **cptr = cp;
  126. X        cptr++;
  127. X        }
  128. X    /*PC = pc ? *pc : 0;*/
  129. X    if (cp = tgetstr("kh", &p))
  130. X        K[KEY_HOME    - KFIRST] = cp;
  131. X    if (cp = tgetstr("ku", &p))
  132. X        K[KEY_UP    - KFIRST] = cp;
  133. X    if (cp = tgetstr("kd", &p))
  134. X        K[KEY_DOWN    - KFIRST] = cp;
  135. X    if (cp = tgetstr("kl", &p))
  136. X        K[KEY_LEFT    - KFIRST] = cp;
  137. X    if (cp = tgetstr("kr", &p))
  138. X        K[KEY_RIGHT    - KFIRST] = cp;
  139. X    if (cp = tgetstr("EN", &p))
  140. X        K[KEY_END    - KFIRST] = cp;
  141. X    if (cp = tgetstr("PU", &p))
  142. X        K[KEY_PAGEUP    - KFIRST] = cp;
  143. X    if (cp = tgetstr("PD", &p))
  144. X        K[KEY_PAGEDOWN    - KFIRST] = cp;
  145. X
  146. X    if (CM == NULL)
  147. X        panic("No cursor move (cm) capability in termcap.");
  148. X    if (UP == NULL)
  149. X        panic("No upline (up) capability in termcap.");
  150. X# if    defined(SIGWINCH)
  151. X    {void ttwinch();
  152. X    signal(SIGWINCH, ttwinch);
  153. X    }
  154. X# endif
  155. X
  156. X    if(!CE) tceeol = ncol;
  157. X    else    tceeol = charcost(CE);
  158. X
  159. X    /* Estimate cost of inserting a line */
  160. X    if (CS && SR)   tcinsl = charcost(CS)*2 + charcost(SR);
  161. X    else if (pAL)   tcinsl = charcost(pAL);
  162. X    else if (AL)    tcinsl = charcost(AL);
  163. X    else            tcinsl = HUGE;   /* make this cost high enough */
  164. X
  165. X    /* Estimate cost of deleting a line */
  166. X    if (CS)         tcdell = charcost(CS)*2 + 1;
  167. X    else if (pDL)   tcdell = charcost(pDL);
  168. X    else if (DL)    tcdell = charcost(DL);
  169. X    else            tcdell = HUGE;   /* make this cost high enough */
  170. X
  171. X    /* Flag to indicate that we can both insert and delete lines */
  172. X    insdel = (AL || pAL) && (DL || pDL);
  173. X
  174. X    if (p >= &tcapbuf[TCAPSLEN])
  175. X        panic("Terminal description too big!\n");
  176. X
  177. X    /* tgoto() doesnt work properly with real termcap -- leave *
  178. X    /* this in for now. */
  179. X# if    1 || defined(MY_TERMCAP)
  180. X    {
  181. X    void close_termcap();
  182. X    close_termcap();
  183. X    }
  184. X# endif
  185. X}
  186. Xttinit1()
  187. X{
  188. X    ttresize();                     /* set nrow & ncol      */
  189. X    flush_col_cache();
  190. X    if (TI) 
  191. X        putpad (TI);     /* init the term */
  192. X    if (IS) 
  193. X        putpad (IS);     /* init the term */
  194. X    if (KS) 
  195. X        putpad(KS);
  196. X}
  197. X/*----------------------------------------
  198. X/* Routine to decypher termcap style strings.
  199. X/* Needed by code in set_term_escapes.
  200. X/*----------------------------------------*/
  201. X
  202. X# define    XDIGIT(x)    (x <= '9' ? x - '0' : \
  203. X                 (x >= 'a' && x <= 'z') ? x - 'a' + 10 : \
  204. X                 (x - 'A' + 10))
  205. Xchar *
  206. Xtcopy_string(dp, bp, delim)
  207. Xregister    char    *dp, *bp;
  208. X{    register int n;
  209. X
  210. X    while (*bp != delim && *bp) {
  211. X        if (*bp == '^') {
  212. X            *dp++ = *++bp & 0x1f;
  213. X            bp++;
  214. X            continue;
  215. X            }
  216. X        if (*bp != '\\') {
  217. X            *dp++ = *bp++;
  218. X            continue;
  219. X            }
  220. X        switch (*++bp) {
  221. X          case 'E':    *dp++ = 0x1b; break;
  222. X          case 'r':    *dp++ = '\r'; break;
  223. X          case 'n':    *dp++ = '\n'; break;
  224. X          case 't':    *dp++ = '\t'; break;
  225. X          case 'b':    *dp++ = '\b'; break;
  226. X          case 'f':    *dp++ = '\f'; break;
  227. X          case '0': case '1': case '2': case '3':
  228. X            n = 0;
  229. X            while (*bp >= '0' && *bp <= '7')
  230. X                n = 8*n + *bp++ - '0';
  231. X            bp--;
  232. X            *dp++ = (char) n;
  233. X            break;
  234. X          case 'x':
  235. X            bp++;
  236. X            n = XDIGIT(*bp);
  237. X            bp++;
  238. X            n = n * 16 + XDIGIT(*bp);
  239. X            *dp++ = (char) n;
  240. X            break;
  241. X          default:    *dp++ = *bp; break;
  242. X          }
  243. X        bp++; 
  244. X        }
  245. X    *dp++ = NULL;
  246. X    return dp;
  247. X}
  248. X
  249. X/*
  250. X * Clean up the terminal, in anticipation of
  251. X * a return to the command interpreter. This is a no-op
  252. X * on the ANSI display. On the SCALD display, it sets the
  253. X * window back to half screen scrolling. Perhaps it should
  254. X * query the display for the increment, and put it
  255. X * back to what it was.
  256. X */
  257. Xvoid
  258. Xtttidy() 
  259. X{
  260. X    if (RS && *RS) putpad (RS);     /* set the term back to normal mode */
  261. X    if (TE && *TE) putpad (TE);     /* set the term back to normal mode */
  262. X    if (KE) 
  263. X        putpad(KE);
  264. X}
  265. X
  266. X/*
  267. X * Move the cursor to the specified
  268. X * origin 0 row and column position. Try to
  269. X * optimize out extra moves; redisplay may
  270. X * have left the cursor in the right
  271. X * location last time!
  272. X */
  273. Xvoid
  274. Xttmove(row, col) 
  275. Xu_int16    row;
  276. Xu_int16    col;
  277. X{
  278. X    char        *tgoto();
  279. X    extern char *HO;
  280. X    if (ttrow == row && ttcol == col)
  281. X        return;
  282. X
  283. X    if (col == 0 && row == 0 && HO)
  284. X        putpad(HO);
  285. X    else if (ttcol == col && row == ttrow+1)
  286. X        ttputpad('\n');
  287. X    else if (ttcol == col+1 && row == ttrow+1) {
  288. X        ttputpad('\n');
  289. X        ttputpad('\b');
  290. X        }
  291. X    else if (ttcol-1 == col && row == ttrow)
  292. X        ttputpad('\b');
  293. X    else if (ttrow == row && pt.pt_escC[0] && col > ttcol && ttcol > 1) {
  294. X        putpad(tgoto(pt.pt_escC, 0, col - ttcol));
  295. X        }
  296. X    else {
  297. X        char *cp = tgoto(CM, (int) col, (int) row);
  298. X/*        int len = strlen(cp);
  299. X        if (row == ttrow && col + len < ttcol) {
  300. X            int i;
  301. X            for (i = 0; i++ < ttcol - col; i++)
  302. X                ttputpad('\b');
  303. X            }
  304. X        else*/
  305. X            putpad(cp);
  306. X        }
  307. X    ttrow = row;
  308. X    ttcol = col;
  309. X}
  310. X/*
  311. X * Erase to end of line.
  312. X */
  313. Xvoid
  314. Xtteeol() 
  315. X{
  316. X    if(CE) putpad(CE);
  317. X    else {
  318. X    register int i=ncol-ttcol;
  319. X    while(i--) ttputc(' ');
  320. X    ttrow = ttcol = HUGE;
  321. X    }
  322. X}
  323. X
  324. Xttclear()
  325. X{
  326. X    if (CL == NULL) {
  327. X        ttmove((u_int16) 0, (u_int16) 0);
  328. X        tteeop();
  329. X        }
  330. X    else {
  331. X        ttrow = 0;
  332. X        ttcol = 0;
  333. X        putpad(CL);
  334. X        }
  335. X}
  336. X/*
  337. X * Erase to end of page.
  338. X */
  339. Xvoid
  340. Xtteeop() 
  341. X{
  342. X    if(CD) putpad(CD);
  343. X    else {
  344. X    putpad(CE);
  345. X    if (insdel) ttdell(ttrow + 1, LI, LI - ttrow - 1);
  346. X    else {          /* do it by hand */
  347. X        register int line;
  348. X        for (line = ttrow + 1; line <= LI; ++line) {
  349. X        ttmove((u_int16) line, (u_int16) 0);
  350. X        tteeol();
  351. X        }
  352. X    }
  353. X    ttrow = ttcol = HUGE;
  354. X    }
  355. X}
  356. X
  357. X/*
  358. X * Make a noise.
  359. X */
  360. Xvoid
  361. Xttbeep() 
  362. X{
  363. X    ttputc(BEL);
  364. X    /*----------------------------------------
  365. X    /*   Adjust cursor because ttputc() thinks
  366. X    /*   BEL moves the cursor.
  367. X    /*----------------------------------------*/
  368. X    ttcol--;
  369. X    ttflush();
  370. X}
  371. Xbeep()
  372. X{
  373. X    ttbeep();
  374. X    return 0;
  375. X}
  376. X
  377. X/*
  378. X * Insert nchunk blank line(s) onto the
  379. X * screen, scrolling the last line on the
  380. X * screen off the bottom.  Use the scrolling
  381. X * region if possible for a smoother display.
  382. X * If no scrolling region, use a set
  383. X * of insert and delete line sequences
  384. X */
  385. Xttinsl(row, bot, nchunk) 
  386. X{
  387. X    register int        i;
  388. X
  389. X    if (row == bot) {           /* Case of one line insert is special  */
  390. X        ttmove((u_int16) row, (u_int16) 0);
  391. X        tteeol();
  392. X        return TRUE;
  393. X    }
  394. X    if (CS && SR) {             /* Use scroll region and back index     */
  395. X        ttwindow(row,bot);
  396. X        ttmove((u_int16) row, (u_int16) 0);
  397. X        while (nchunk--) putpad(SR);
  398. X        /*ttnowindow();*/
  399. X        return TRUE;
  400. X        }
  401. X    if (insdel) {
  402. X        ttmove((u_int16) (1+bot-nchunk), (u_int16) 0);
  403. X        if (pDL) 
  404. X            putpad (tgoto(pDL, 0, nchunk));
  405. X        else 
  406. X            for (i=0; i<nchunk; i++)/* For all lines in the chunk */
  407. X                putpad(DL);
  408. X        ttmove((u_int16) row, (u_int16) 0);
  409. X        if (pAL) 
  410. X            putpad (tgoto(pAL, 0, nchunk));
  411. X        else 
  412. X            for (i=0; i<nchunk; i++)/* For all lines in the chunk*/
  413. X                putpad(AL);
  414. X        ttrow = HUGE;
  415. X        ttcol = HUGE;
  416. X        return TRUE;
  417. X        }
  418. X    return FALSE;
  419. X}
  420. X
  421. X/*
  422. X * Delete nchunk line(s) from "row", replacing the
  423. X * bottom line on the screen with a blank line. 
  424. X * Unless we're using the scrolling region, this is 
  425. X * done with a crafty sequences of insert and delete 
  426. X * lines.  The presence of the echo area makes a
  427. X * boundry condition go away.
  428. X */
  429. Xttdell(row, bot, nchunk)
  430. X{    register int        i;
  431. X
  432. X    if (row == bot) {           /* One line special case        */
  433. X        ttmove((u_int16) row, (u_int16) 0);
  434. X        tteeol();
  435. X        return TRUE;
  436. X        }
  437. X    if (CS) {                   /* scrolling region     */
  438. X        ttwindow(row, bot);
  439. X        ttmove((u_int16) bot, (u_int16) 0);
  440. X        while (nchunk--) ttputc(LF);
  441. X        return TRUE;
  442. X        }
  443. X    if(insdel) {
  444. X        ttmove((u_int16) row, (u_int16) 0);
  445. X        if (pDL) 
  446. X            putpad (tgoto(pDL, 0, nchunk));
  447. X        else 
  448. X            for (i=0; i<nchunk; i++)
  449. X                putpad(DL);
  450. X        ttmove((u_int16) (1+bot-nchunk), (u_int16) 0);
  451. X        if (pAL) 
  452. X            putpad (tgoto(pAL, 0, nchunk));
  453. X        else 
  454. X            for (i=0; i<nchunk; i++)
  455. X                putpad(AL);
  456. X        ttrow = HUGE;
  457. X        ttcol = HUGE;
  458. X        return TRUE;
  459. X        }
  460. X    return FALSE;    
  461. X}
  462. X
  463. X/*
  464. X * This routine sets the scrolling window
  465. X * on the display to go from line "top" to line
  466. X * "bot" (origin 0, inclusive). The caller checks
  467. X * for the pathalogical 1 line scroll window that
  468. X * doesn't work right, and avoids it. The "ttrow"
  469. X * and "ttcol" variables are set to a crazy value
  470. X * to ensure that the next call to "ttmove" does
  471. X * not turn into a no-op (the window adjustment
  472. X * moves the cursor).
  473. X * 
  474. X */
  475. Xvoid
  476. Xttwindow(top, bot)
  477. X{
  478. X    if (CS && (tttop!=top || ttbot!=bot)) {
  479. X        putpad(tgoto(CS, bot, top));
  480. X        ttrow = HUGE;                   /* Unknown.             */
  481. X        ttcol = HUGE;
  482. X        tttop = top;                    /* Remember region.     */
  483. X        ttbot = bot;
  484. X    }
  485. X}
  486. X
  487. X/*
  488. X * Set the current writing color to the
  489. X * specified color. Watch for color changes that are
  490. X * not going to do anything (the color is already right)
  491. X * and don't send anything to the display.
  492. X * The rainbow version does this in putline.s on a
  493. X * line by line basis, so don't bother sending
  494. X * out the color shift.
  495. X */
  496. Xstatic    int    tthue = -1;
  497. Xstatic    int     tt_fg = -1;
  498. Xstatic    int    tt_bg = -1;
  499. Xstatic int gso = FALSE;
  500. Xvoid
  501. Xflush_col_cache()
  502. X{
  503. X    tthue = tt_fg = tt_bg = -1;
  504. X}
  505. Xvoid
  506. Xttcolor(color)
  507. X{    int    fg, bg;
  508. X
  509. X    if (tthue == color)
  510. X        return;
  511. X    tthue = color;
  512. X    if (!pt.pt_color) {
  513. X        if (color == FG(col_table.c_normal) ||
  514. X            color == FG(col_table.c_messages)) {
  515. X            putpad(SE); 
  516. X            }
  517. X        else if (color == FG(col_table.c_select) ||
  518. X            color == FG(col_table.c_error)) {
  519. X            putpad(SE);
  520. X            putpad(MD);
  521. X            }
  522. X        else {
  523. X            putpad(SO);
  524. X            }
  525. X        return;
  526. X        }
  527. X    fg = (color & FG_COLOR) >> FG_SHIFT;
  528. X    bg = (color & BG_COLOR) >> BG_SHIFT;
  529. X    if (fg != tt_fg) {
  530. X        putpad(colors.fg[fg]);
  531. X        tt_fg = fg;
  532. X        }
  533. X    if (bg != tt_bg) {
  534. X        putpad(colors.bg[bg]);
  535. X        tt_bg = bg;
  536. X        }
  537. X}
  538. Xvoid
  539. Xttresize() 
  540. X{
  541. X    setttysize();
  542. X    if (nrow < 1)
  543. X        nrow = 1;
  544. X    if (ncol < 1)
  545. X        ncol = 1;
  546. X}
  547. Xvoid
  548. Xttwinch()
  549. X{
  550. X# if    defined(SIGWINCH)
  551. X    void    ttwinch1();
  552. X    
  553. X    int oncol = ncol;
  554. X    int    onrow = nrow;
  555. X    ttresize();
  556. X    signal(SIGWINCH, ttwinch);
  557. X    update();
  558. X# endif
  559. X}
  560. Xvoid
  561. Xttwinch1(oncol, onrow, ncol, nrow)
  562. X{    register WINDOW *wp;
  563. X    extern    int    sgarbf;
  564. X    int    diffcol, diffrow;
  565. X    
  566. X    vtinit1();
  567. X    diffcol = ncol - oncol;
  568. X    diffrow = nrow - onrow;
  569. X    for (wp = wheadp; wp; wp = wp->w_wndp) {
  570. X        int     right_edge;
  571. X        int    last_line;
  572. X        /*----------------------------------------
  573. X        /*   Adjust window width only if its right
  574. X        /*   hand edge touches the right hand edge
  575. X        /*   of the window.
  576. X        /*----------------------------------------*/
  577. X        right_edge = wp->w_x + wp->w_w;
  578. X        last_line = wp->w_y + wp->w_h;
  579. X        if (wp->w_tiled)
  580. X            right_edge++;
  581. X        if (right_edge == oncol)
  582. X            wp->w_w += diffcol;
  583. X        /*----------------------------------------
  584. X        /*   Adjust window height if window's
  585. X        /*   bottom line touches bottom of screen.
  586. X        /*----------------------------------------*/
  587. X        if (last_line == onrow - 3)
  588. X            wp->w_h += diffrow;
  589. X        }
  590. X    sgarbf = TRUE;
  591. X}
  592. X
  593. Xstatic int cci;
  594. X
  595. Xstatic void                 /* fake char output for charcost() */
  596. Xfakec(c) char c; 
  597. X{
  598. X#ifdef  lint
  599. X    c++;
  600. X#endif
  601. X    cci++;
  602. X}
  603. X
  604. X/* calculate the cost of doing string s */
  605. Xcharcost (s) char *s; 
  606. X{
  607. X    cci = 0;
  608. X
  609. X    tputs(s, nrow, fakec);
  610. X    return cci;
  611. X}
  612. Xvoid
  613. Xputpad(str) 
  614. Xchar *str; 
  615. X{
  616. X    if (str == NULL)
  617. X        return;
  618. X/*    if (str == SO) {
  619. X        if (gso)
  620. X            return;
  621. X        gso = TRUE;
  622. X        }
  623. X    else if (str == SE) {
  624. X        if (!gso)
  625. X            return;
  626. X        gso = FALSE;
  627. X        }    */
  628. X    tputs(str, 1, ttputpad);
  629. X}
  630. Xvoid
  631. Xttspace(n, space, stay)
  632. X{    u_int16    oldrow = ttrow;
  633. X    u_int16    oldcol = ttcol;
  634. X
  635. X    if (n <= 0)
  636. X        return;
  637. X    ttputc(space);
  638. X    if (--n <= 0)
  639. X        return;
  640. X    if (pt.pt_space[0]) {
  641. X        putpad(tgoto(pt.pt_space, 0, n));
  642. X        if (!stay)
  643. X            ttmove(oldrow, oldcol + n + 1);
  644. X        }
  645. X    else {
  646. X        while (n-- > 0)
  647. X            ttputc(space);
  648. X        }
  649. X    if (stay)
  650. X        ttmove(oldrow, oldcol);
  651. X    
  652. X}
  653. Xttrepeat(ch, n)
  654. X{
  655. X    if (n > 12 && pt.pt_repeat[0]) {
  656. X        ttputc(ch);
  657. X        putpad(tgoto(pt.pt_repeat, 0, n-1));
  658. X        ttmove(ttrow, ttcol + n - 1);
  659. X        }
  660. X    while (n-- > 0)
  661. X        ttputc(ch);
  662. X
  663. X
  664. X}
  665. X
  666. SHAR_EOF
  667. echo "File ./tty.c is complete"
  668. chmod 0444 ./tty.c || echo "restore of ./tty.c fails"
  669. mkdir . >/dev/null 2>&1
  670. echo "x - extracting ./ttyio.c (Text)"
  671. sed 's/^X//' << 'SHAR_EOF' > ./ttyio.c &&
  672. X/**************************************************************
  673. X *
  674. X *    CRISP - Custom Reduced Instruction Set Programmers Editor
  675. X *
  676. X *    (C) Paul Fox, 1989
  677. X *    43, Jerome Close          Tel: +44 6284 4222
  678. X *        Marlow
  679. X *         Bucks.
  680. X *        England SL7 1TX
  681. X *
  682. X *
  683. X *    Please See COPYRIGHT notice.
  684. X *
  685. X **************************************************************/
  686. X
  687. X# include        "list.h"
  688. XSCCSID("@(#) ttyio.c 1.15, (C) P. Fox");
  689. X
  690. X# if    defined(SUN)
  691. X#     include    <sys/time.h>
  692. X#     include    <termio.h>
  693. X# endif
  694. X# if    defined(XENIX)
  695. X#     include    <termio.h>
  696. X# endif
  697. X
  698. X
  699. X
  700. X# define    TTY_FD    0
  701. X# define    BIT(x)    (1 << (x))
  702. X
  703. X# if    defined(SELECT)
  704. X# include    <sys/types.h>
  705. X# include    <sys/time.h>
  706. X
  707. X# endif
  708. Xlong    sel_bits = BIT(TTY_FD);
  709. X
  710. X# define    CENTISECONDS    5    /* x .01 seconds */
  711. Xvoid    ttflush();
  712. X
  713. X#define NOBUF   136                     /* Output buffer size.          */
  714. X
  715. Xlong    st_charout;            /* Number of characters output.    */
  716. X
  717. Xchar    obuf[NOBUF+10];                 /* Output buffer.               */
  718. Xint     nobuf;                          /* buffer count                 */
  719. Xint    timeout_flag = FALSE;    /* TRUE when we are in VMIN/VTIME mode.*/
  720. Xint    reading_char;
  721. Xunsigned char kbdq = 0;
  722. Xextern int ega43_flag;
  723. Xint old_ega_flag = -1;
  724. X
  725. Xu_int16        nrow;                   /* Terminal size, rows.         */
  726. Xu_int16        ncol;                   /* Terminal size, columns.      */
  727. X
  728. X/*
  729. X * This function gets called once, to set up
  730. X * the terminal channel.  This version turns off flow
  731. X * control.  This may be wrong for your system, but no
  732. X * good solution has really been found (daveb).
  733. X */
  734. Xvoid
  735. Xttopen()
  736. X{
  737. X    sys_open();
  738. X    ttinit1();
  739. X}
  740. Xvoid
  741. Xtttimeout(yes)
  742. X{
  743. X    if (yes == timeout_flag)
  744. X        return;
  745. X    timeout_flag = yes;
  746. X    sys_timeout(yes);
  747. X}
  748. X/*
  749. X * This function gets called just
  750. X * before we go back home to the shell. Put all of
  751. X * the terminal parameters back.
  752. X */
  753. Xvoid
  754. Xttclose()
  755. X{
  756. X    ttflush();
  757. X    sys_close();
  758. X    old_ega_flag = -1;
  759. X}
  760. X
  761. X/*
  762. X * Write character to the display.
  763. X * Characters are buffered up, to make things
  764. X * a little bit more efficient.
  765. X */
  766. Xvoid
  767. Xttputpad(c)
  768. X{
  769. X    if (nobuf >= NOBUF)
  770. X        ttflush();
  771. X    obuf[nobuf++] = (char) c;
  772. X}
  773. Xvoid
  774. Xttputs(str)
  775. Xregister char    *str;
  776. X{
  777. X    while (*str)
  778. X        ttputc(*str++);
  779. X}
  780. Xvoid
  781. Xttputc(c)
  782. Xregister int c;
  783. X{
  784. X    extern int scr_attr;
  785. X    register int    color = c & COLOR_MASK;
  786. X    extern int AM;
  787. X
  788. X    if (nobuf >= NOBUF)
  789. X        ttflush();
  790. X
  791. X    ttcolor(color);
  792. X
  793. X    c &= 0xff;
  794. X/*    if (c & 0x80 && c < (0x80 + ' ')) {*/
  795. X    if (c & 0x80) {
  796. X        if (c >= CH_MIN && c <= CH_MAX) {
  797. X            char    *cp = "?";
  798. X            switch (c) {
  799. X              case CH_HORIZONTAL:    cp = pt.pt_horizontal; break;
  800. X              case CH_VERTICAL:    cp = pt.pt_vertical; break;
  801. X              case CH_TOP_LEFT:    cp = pt.pt_top_left; break;
  802. X              case CH_TOP_RIGHT:    cp = pt.pt_top_right; break;
  803. X              case CH_BOT_LEFT:    cp = pt.pt_bot_left; break;
  804. X              case CH_BOT_RIGHT:    cp = pt.pt_bot_right; break;
  805. X              case CH_TOP_JOIN:    cp = pt.pt_top_join; break;
  806. X              case CH_BOT_JOIN:    cp = pt.pt_bot_join; break;
  807. X              case CH_LEFT_JOIN:    cp = pt.pt_left_join; break;
  808. X              case CH_RIGHT_JOIN:    cp = pt.pt_right_join; break;
  809. X              case CH_CROSS:    cp = pt.pt_cross; break;
  810. X                    }
  811. X            strcpy(obuf + nobuf, cp);
  812. X            nobuf += strlen(cp);
  813. X            }
  814. X        else if (c >= 0x80 + ' ')
  815. X            goto hell;
  816. X        else    {
  817. X            c &= 0x7f;
  818. X            if (c == 0x1b && pt.pt_escape[0])
  819. X                strcpy(obuf+nobuf, pt.pt_escape);
  820. X            else
  821. X                sprintf(obuf+nobuf, pt.pt_character, c ? c : 0x80);
  822. X            nobuf += strlen(obuf+nobuf);
  823. X            }
  824. X        goto end_of_function;
  825. X        }
  826. X    if (c == 0)
  827. X        return;
  828. Xhell:
  829. X    obuf[nobuf++] = (char) c;
  830. X    if (c == '\b') {
  831. X        ttcol--;
  832. X        return;
  833. X        }
  834. Xend_of_function:
  835. X    if (++ttcol >= ncol && AM) {
  836. X        ttcol = 0;
  837. X        ttrow++;
  838. X        }        
  839. X}
  840. X
  841. Xvoid
  842. Xttflush()
  843. X{    extern int background;
  844. X
  845. X    if (nobuf != 0) {
  846. X        st_charout += nobuf;
  847. X        if (background == FALSE)
  848. X            sys_write(1, obuf, nobuf);
  849. X        nobuf = 0;
  850. X    }
  851. X}
  852. XKEY
  853. Xgetkey()
  854. X{
  855. X    int    n;
  856. X    unsigned char ch;
  857. X    extern int num_pty;
  858. X    extern long time_last_key_pressed;
  859. X    KEY    key;
  860. X    static unsigned char    buf[32];    /* Buffer for current key being read in */
  861. X    static unsigned char *bufptr = NULL;
  862. X    unsigned char    *cp = buf;
  863. X    int    pass2 = FALSE;
  864. X    extern int push_cnt;
  865. X# if    defined(SELECT)
  866. X    struct timeval timeout;
  867. X    struct timeval *tp = NULL;
  868. X    
  869. X    timeout.tv_sec = 0;
  870. X    timeout.tv_usec = 0;
  871. X# endif
  872. X
  873. X    if (push_cnt)
  874. X        return get_push();
  875. X        
  876. X    if (bufptr) {
  877. X        ch = *bufptr++;
  878. X        if (*bufptr == NULL)
  879. X            bufptr = NULL;
  880. X        return ch;
  881. X        }
  882. X        
  883. X    while (1) {
  884. X        extern int child_sig;
  885. X        extern void proc_wait();
  886. X        /*----------------------------------------
  887. X        /*   Check to see if clock has gone off
  888. X        /*   and we need to call somebody. We can
  889. X        /*   only safely do this whilst we are NOT
  890. X        /*   reading a character from the keyboard.
  891. X        /*----------------------------------------*/
  892. X        clock_check();
  893. X        if (kbdq) {
  894. X            ch = kbdq;
  895. X            kbdq = 0;
  896. X            goto got_char;
  897. X            }
  898. X        /*----------------------------------------
  899. X        /*   If SIGCLD gone off then we should be
  900. X        /*   safe here to go and process it.
  901. X        /*----------------------------------------*/
  902. X        if (child_sig)
  903. X            proc_wait(-1);
  904. X        
  905. X        reading_char = TRUE;
  906. X# if    defined(SELECT)
  907. X        if (pass2) {
  908. X            timeout.tv_usec = CENTISECONDS * 100 * 1000;
  909. X            tp = &timeout;
  910. X            }
  911. X        if (tp || num_pty) {
  912. X            int    fd, bits;
  913. X            long readbits = sel_bits;
  914. X            long    kbd_ready;
  915. X            long    pty_ready;
  916. X            int nfds = select(32, &readbits, (long *) NULL, (long *) NULL,
  917. X                tp);
  918. X            if (nfds < 0)
  919. X                continue;
  920. X            kbd_ready = BIT(TTY_FD) & readbits;
  921. X            pty_ready = FALSE;
  922. X            /*----------------------------------------
  923. X            /*   Handle all pty's first.
  924. X            /*----------------------------------------*/
  925. X            for (fd = 0, bits = 0; readbits && bits < 32; 
  926. X                 bits++, readbits >>= 1, fd++) {
  927. X                if (fd == TTY_FD)
  928. X                         continue;
  929. X                if ((BIT(fd) & readbits) == 0)
  930. X                    continue;
  931. X                p_poll();
  932. X                pty_ready = TRUE;
  933. X                }
  934. X            if (kbdq)
  935. X                continue;
  936. X            if (!kbd_ready) {
  937. X                if (tp && pty_ready == FALSE)
  938. X                    goto return_ch;
  939. X                continue;
  940. X                }
  941. X            }
  942. X# endif
  943. X# if    !defined(SELECT)
  944. X        tttimeout(pass2);
  945. X# endif
  946. X        /*----------------------------------------
  947. X        /*   Check to see if we have anything in
  948. X        /*   playback buffer, before finally going
  949. X        /*   to the keyboard for a character.
  950. X        /*----------------------------------------*/
  951. X        if ((ch = grab_char()) == 0) {
  952. X            if (sys_getchar(TTY_FD, &ch, 1) != 1) {
  953. X                if (pass2)
  954. X                    goto return_ch;
  955. X                continue;
  956. X                }
  957. X            }
  958. X
  959. Xgot_char:
  960. X        reading_char = FALSE;
  961. X        *cp++ = ch;
  962. X        *cp = NULL;
  963. X        time_last_key_pressed = time((long *) 0);
  964. X        key = check_key(buf, cp - buf);
  965. X        if (key > 0) {
  966. X            store_char(key);
  967. X            return key;
  968. X            }
  969. X        if (key == 0) {
  970. Xreturn_ch:        
  971. X            if (buf[1])
  972. X                bufptr = &buf[1];
  973. X            store_char (buf[0]);
  974. X            return buf[0];
  975. X            }
  976. X        pass2 = TRUE;
  977. X        }
  978. X}
  979. X
  980. Xtypeahead()                         
  981. X{
  982. X    if (kbdq)
  983. X        return kbdq;
  984. X
  985. X    if (kbdq = grab_char())
  986. X        return kbdq;
  987. X
  988. X    kbdq = sys_checkc();
  989. X    return kbdq;
  990. X}
  991. X
  992. X
  993. Xvoid
  994. Xpanic(s)
  995. Xchar *s;
  996. X{
  997. X    u_close();
  998. X    vttidy();
  999. X    fprintf(stderr, "CRISP PANIC: %s\r\n", s);
  1000. X    exit(1);
  1001. X}
  1002. X
  1003. Xdo_ega()
  1004. X{    int    arg = argv[1].l_flags == F_NULL ? 0 : argv[1].l_int;
  1005. X
  1006. X    accumulator = ega43_flag ? 43 : 25;
  1007. X    if (argv[1].l_flags == F_NULL)
  1008. X        return;
  1009. X        
  1010. X    if (arg == 43)
  1011. X        arg = 1;
  1012. X    else if (arg == 25)
  1013. X        arg = 0;
  1014. X    ega_switch(arg);
  1015. X}
  1016. Xvoid
  1017. Xsetttysize()
  1018. X{    extern char *ggetenv();
  1019. X    extern int    AM;
  1020. X    
  1021. X#ifdef  TIOCGWINSZ
  1022. X    struct winsize    winsize;
  1023. X
  1024. X    if (ioctl(0, TIOCGWINSZ, (char *) &winsize) == 0) {
  1025. X        nrow = winsize.ws_row;
  1026. X        ncol = winsize.ws_col;
  1027. X        }
  1028. X    if (nrow == 0 || ncol == 0)
  1029. X#endif
  1030. X    if ((nrow= (u_int16) tgetnum ("li")) == 0
  1031. X       || (ncol= (u_int16) tgetnum ("co")) == 0) {
  1032. X        nrow = 24;
  1033. X        ncol = 80;
  1034. X        }
  1035. X# if    defined(CONS_GET)
  1036. X    {extern int console_mode;
  1037. X    if (console_mode > 0) {
  1038. X        switch (console_mode) {
  1039. X          case M_ENH_C80x43:
  1040. X            ega_switch(1);
  1041. X            nrow = 43;
  1042. X            break;
  1043. X          case M_ENH_C80x25:
  1044. X            ega_switch(0);
  1045. X            nrow = 25;
  1046. X            break;
  1047. X          }
  1048. X        }
  1049. X    }
  1050. X# endif
  1051. X    if (ggetenv("LINES")) {
  1052. X        nrow = atoi(ggetenv("LINES"));
  1053. X        AM = FALSE;
  1054. X        }
  1055. X    if (ggetenv("COLUMNS")) {
  1056. X        ncol = atoi(ggetenv("COLUMNS"));
  1057. X        AM = FALSE;
  1058. X        }
  1059. X}
  1060. Xega_switch(flag)
  1061. X{    extern int sgarbf;
  1062. X    extern void ttwinch1();
  1063. X    int    onrow = nrow;
  1064. X        
  1065. X    if (flag)
  1066. X        flag = 1;
  1067. X
  1068. X    if (old_ega_flag == flag)
  1069. X        return;
  1070. X    
  1071. X    old_ega_flag = ega43_flag = flag;
  1072. X    if (flag) {
  1073. X# if    defined(SW_ENHC80x43)
  1074. X        ioctl(1, SW_ENHC80x43, 1);
  1075. X        nrow = 43;
  1076. X# endif
  1077. X        ttwinch1(ncol, onrow, ncol, nrow);
  1078. X        }
  1079. X    else {
  1080. X# if    defined(SW_ENHC80x25)
  1081. X        ioctl(1, SW_ENHC80x25, 1);
  1082. X        nrow = 25;
  1083. X# endif
  1084. X        ttwinch1(ncol, onrow, ncol, nrow);
  1085. X        }
  1086. X    flush_col_cache();
  1087. X}
  1088. X
  1089. SHAR_EOF
  1090. chmod 0444 ./ttyio.c || echo "restore of ./ttyio.c fails"
  1091. mkdir . >/dev/null 2>&1
  1092. echo "x - extracting ./ttykbd.c (Text)"
  1093. sed 's/^X//' << 'SHAR_EOF' > ./ttykbd.c &&
  1094. X/**************************************************************
  1095. X *
  1096. X *    CRISP - Custom Reduced Instruction Set Programmers Editor
  1097. X *
  1098. X *    (C) Paul Fox, 1989
  1099. X *    43, Jerome Close          Tel: +44 6284 4222
  1100. X *        Marlow
  1101. X *         Bucks.
  1102. X *        England SL7 1TX
  1103. X *
  1104. X *
  1105. X *    Please See COPYRIGHT notice.
  1106. X *
  1107. X **************************************************************/
  1108. X# include    "list.h"
  1109. X# include    "alt.h"
  1110. X
  1111. XSCCSID("@(#) ttykbd.c 1.11, (C) P. Fox");
  1112. X
  1113. X/*
  1114. X0x80-0x8b    128-139        F1-F12
  1115. X0x8c-0x97    140-151        SHIFT-F1  -  SHIFT-F12
  1116. X0x98-0xA3    152-163        CTRL-F1   -  CTRL-F12
  1117. X0xA4-0xAF    164-175        ALT-F1    -  ALT-F12
  1118. X0xB0-0xC9    176-201        ALT-A      -  ALT-Z
  1119. X0xCA-0xD3    202-211        Key-0, Key-9
  1120. X            0xCA/202=INS
  1121. X            0xCB/203=END,  0xCC/204=DOWN, 0xCD/205=PgDn,
  1122. X            0xCE/206=LEFT, 0xCF/207=5,    0xD0/208=RIGHT,
  1123. X            0xD1/209=HOME, 0xD2/210=UP,   0xD3/211=PgUp
  1124. X0xD4/212=DEL, 0xD5/213=+, 0xD6/214=-, 0xD7/215=*
  1125. X0xD8-0xE5    216-229        CTRL-0 .. CTRL-9, DEL, +, -, *
  1126. X            0xDF/223=Ctrl-Home    0xD9/217=Ctrl-End
  1127. X            0xE1/225=Ctrl-PgUp    0xDB/219=Ctrl-Pgdn
  1128. X            0xDC/220=Ctrl-<-    0xDE/222=Ctrl- ->
  1129. X0xE6        230    Back-tab
  1130. X*/
  1131. X# define    MAX_PUSHBACK    12
  1132. X
  1133. Xint    reading_char = FALSE;
  1134. Xstatic    u_char    key_buf[16];
  1135. Xextern    long    time_last_key_pressed;
  1136. Xu_char    push_buf[MAX_PUSHBACK];
  1137. Xint        push_cnt = 0;
  1138. Xchar        user_call[64];    /* Last macro called from keyboard by user*/
  1139. X
  1140. Xchar    *aitokey();
  1141. Xstatic    short    akeytoi();
  1142. Xtypedef    char    *KEYBOARD[NKEYS];
  1143. Xtypedef    struct    MAP    {
  1144. X        char    *m_keys;    /* Key sequence.           */
  1145. X        char    *m_value;    /* String assigned to.           */
  1146. X        int    m_flags;    /* Tells us whether m_value is a   */
  1147. X                    /* string or a list.           */
  1148. X        } MAP;
  1149. X
  1150. X# define    K_ALLOC        0x01    /* Key has been alloc'ed and should*/
  1151. X                    /* be freed when finished with.       */
  1152. X# define    K_LIST        0x02    /* Key is assigned to a list.       */
  1153. Xstruct    kbd_stk {
  1154. X    int        k_id;
  1155. X    int        k_ref;        /* Reference count for this keyboard. */
  1156. X                    /* When this becomes zero, we may free*/
  1157. X                    /* it. Otherwise, it still exists in  */
  1158. X                    /* the keyboard stack.              */
  1159. X    u_char        k_flags[NKEYS];
  1160. X    KEYBOARD    k_keys;
  1161. X    Head_p        k_maps;        /* Multicharacter key combinations.    */
  1162. X    };
  1163. X
  1164. XHead_p    hd_kbd;
  1165. XHead_p    hd_kstk;
  1166. Xstruct    kbd_stk    *kp;
  1167. X#define KFIRST  0x0080                  /* First special.               */
  1168. Xextern char    *K[];
  1169. Xchar    character;
  1170. Xint    kid = 1;
  1171. X
  1172. Xextern struct k_tbl k_tbl[];
  1173. Xvoid
  1174. Xkey_init()
  1175. X{    extern char    *chk_alloc();
  1176. X    int    i;
  1177. X    struct kbd_stk *kptr;
  1178. X
  1179. X    hd_kbd = ll_init();
  1180. X    hd_kstk = ll_init();
  1181. X
  1182. X    kptr = (struct kbd_stk *) chk_alloc(sizeof (struct kbd_stk));
  1183. X    kptr->k_id = kid++;
  1184. X    kptr->k_ref = 1;
  1185. X    kptr->k_maps = ll_init();
  1186. X    for (i = 0; i < NKEYS; i++) {
  1187. X        kptr->k_keys[i] = NULL;
  1188. X        kptr->k_flags[i] = 0;
  1189. X        }
  1190. X    for (i = 0; k_tbl[i].name; i++) {
  1191. X        kptr->k_keys[k_tbl[i].key] = k_tbl[i].name;
  1192. X        kptr->k_flags[k_tbl[i].key] = 0;
  1193. X        }
  1194. X    ll_push(hd_kbd, (char *) kptr);
  1195. X    kp = kptr;
  1196. X    K[BACK_TAB - KFIRST] = strdup("\033[Z");
  1197. X}
  1198. Xkbd_type()
  1199. X{
  1200. X    register    int    i;
  1201. X
  1202. X    for (i = 0; i < 127; i++) {
  1203. X        if (kp->k_keys[i] && kp->k_flags[i] & K_ALLOC)
  1204. X            chk_free(kp->k_keys[i]);
  1205. X        kp->k_keys[i] = NULL;
  1206. X        }
  1207. X    
  1208. X    return 0;
  1209. X}
  1210. Xpush_back()
  1211. X{
  1212. X    push_back1((int) argv[1].l_int);
  1213. X
  1214. X    return 0;
  1215. X}
  1216. Xpush_back1(ch)
  1217. X{
  1218. X    if (push_cnt < MAX_PUSHBACK)
  1219. X        push_buf[push_cnt++] = ch;
  1220. X}
  1221. Xget_push()
  1222. X{    int    ch;
  1223. X    register int i;
  1224. X    if (push_cnt) {
  1225. X        ch = push_buf[0];
  1226. X        for (i = 0; i < MAX_PUSHBACK - 1; i++)
  1227. X            push_buf[i] = push_buf[i+1];
  1228. X        push_cnt--;
  1229. X        return ch;
  1230. X        }
  1231. X    return 0;
  1232. X}
  1233. Xassign_to_key()
  1234. X{    int    key;
  1235. X    char    *cp;
  1236. X    char    *macro_name;
  1237. X    int    flags = K_ALLOC;
  1238. X    char    buf1[80];
  1239. X    char    buf[BUFSIZ];
  1240. X
  1241. X    if ((cp = get_arg1("Enter key: ", buf, sizeof buf)) == NULL)
  1242. X        return;
  1243. X    key = akeytoi(cp);
  1244. X
  1245. X    if (argc < 3 || argv[2].l_flags == F_NULL) {
  1246. X        if (ereply("Enter macro name to assign: ", buf1, sizeof buf1)
  1247. X            != TRUE)
  1248. X            return;
  1249. X        macro_name = strdup(buf1);
  1250. X        }
  1251. X    else if (argv[2].l_flags == F_LIST) {
  1252. X        LIST    *copy_list();
  1253. X        macro_name = (char *) copy_list(argv[2].l_list);
  1254. X        flags = K_LIST | K_ALLOC;
  1255. X        }
  1256. X    else
  1257. X        macro_name = strdup(get_str(2));
  1258. X
  1259. X    if (key >= 0) {
  1260. X        free_key(key);
  1261. X        kp->k_keys[key] = macro_name;
  1262. X        kp->k_flags[key] = flags;
  1263. X        }
  1264. X    else {
  1265. X        MAP *mp = (MAP *) chk_alloc (sizeof (MAP));
  1266. X        mp->m_keys = strdup(key_buf);
  1267. X        mp->m_value = macro_name;
  1268. X        mp->m_flags = flags;
  1269. X        ll_push(kp->k_maps, (char *) mp);
  1270. X        return;
  1271. X        }
  1272. X}
  1273. X
  1274. Xfree_key(key)
  1275. X{
  1276. X    if (kp->k_flags[key] & K_ALLOC)
  1277. X        chk_free(kp->k_keys[key]);
  1278. X}
  1279. Xstatic short
  1280. Xakeytoi(cp)
  1281. Xregister char *cp;
  1282. X{
  1283. X    int    width;
  1284. X
  1285. X    for (width = 0; *cp; width++) {
  1286. X        if (*cp == '<') {
  1287. X            key_buf[width] = (u_char) new_akeytoi(cp);
  1288. X            while (*cp)
  1289. X                if (*cp++ == '>')
  1290. X                    break;
  1291. X            }
  1292. X        else if (*cp == '#') {
  1293. X            key_buf[width] = (u_char) atoi(++cp);
  1294. X            while (isdigit(*cp))
  1295. X                cp++;
  1296. X            }
  1297. X        else {
  1298. X            key_buf[width] = 0;
  1299. X            if (*cp == '%')
  1300. X                cp++;
  1301. X            if (*cp == '\\')
  1302. X                key_buf[width] = (u_char) *++cp;
  1303. X            else if (*cp == '^')
  1304. X                key_buf[width] = (u_char) *++cp & 0x1f;
  1305. X            else
  1306. X                key_buf[width] = (u_char) *cp;
  1307. X            cp++;
  1308. X            }
  1309. X        if (width >= sizeof key_buf)
  1310. X            break;
  1311. X        }
  1312. X    if (width == 1)
  1313. X        return key_buf[0];
  1314. X    key_buf[width] = 0;
  1315. X    return -1;
  1316. X}
  1317. Xkey_to_int()
  1318. X{    
  1319. X    accumulator = akeytoi(get_str(1));
  1320. X    return 0;
  1321. X}
  1322. Xint_to_key()
  1323. X{
  1324. X    strl_acc_assign(aitokey((short) argv[1].l_int));
  1325. X    return 0;
  1326. X}
  1327. Xcheck_key(buf, len)
  1328. Xchar *buf;
  1329. X{
  1330. X    register char **cpp;
  1331. X    List_p    lp;
  1332. X    KEY key;
  1333. X    
  1334. X    /*--------------------------------------
  1335. X     *   Check for normal function keys first.
  1336. X     *--------------------------------------*/
  1337. X    for (cpp = K; cpp < &K[NFKEYS]; cpp++) {
  1338. X        if (*cpp == NULL)
  1339. X            continue;
  1340. X        if (strcmp(*cpp, buf) == 0)
  1341. X            return (KEY) (cpp - K + KFIRST);
  1342. X        if (strncmp(*cpp, buf, len) == 0)
  1343. X            return -1;
  1344. X        }
  1345. X    /*--------------------------------------
  1346. X     *   Check for multiple characters key
  1347. X     *   sequences.
  1348. X     *--------------------------------------*/
  1349. X    for (key = KFIRST + NFKEYS, lp = ll_first(kp->k_maps); lp; 
  1350. X        key++, lp = ll_next(lp)) {
  1351. X        MAP *mp = (MAP *) ll_elem(lp);
  1352. X        if (strcmp(buf, mp->m_keys) == 0)
  1353. X            return key;
  1354. X        if (strcmp(buf, mp->m_keys, len) == 0)
  1355. X            return -1;
  1356. X        }
  1357. X    return 0;
  1358. X}
  1359. X# if 0
  1360. XKEY
  1361. Xgetkey()
  1362. X{    register char    **cpp;
  1363. X    static unsigned char    buf[12];
  1364. X    static unsigned char    *bufptr = NULL;
  1365. X    static unsigned char    *cp;
  1366. X    static int    l;
  1367. X    int    i;
  1368. X    unsigned char ch;
  1369. X    int    timeout = FALSE;
  1370. X    List_p    lp;
  1371. X    KEY    key;
  1372. X    int    ambiguous;
  1373. X
  1374. X    if (push_cnt) {
  1375. X        ch = push_buf[0];
  1376. X        for (i = 0; i < MAX_PUSHBACK - 1; i++)
  1377. X            push_buf[i] = push_buf[i+1];
  1378. X        push_cnt--;
  1379. X        return ch;
  1380. X        }
  1381. X
  1382. X    if (bufptr) {
  1383. X        ch = *bufptr++;
  1384. X        if (*bufptr == NULL)
  1385. X            bufptr = NULL;
  1386. X        return ch;
  1387. X        }
  1388. X    cp = buf;
  1389. X    l = 0;
  1390. X    while (1) {
  1391. X        tttimeout(timeout);
  1392. X
  1393. X        reading_char = TRUE;
  1394. X        if (ch = *cp = (char) ttgetc()) {
  1395. X            extern long time();
  1396. X            store_char(*cp++);
  1397. X            *cp = NULL;
  1398. X            l++;
  1399. X            time_last_key_pressed = time((long *) 0);
  1400. X            }
  1401. X        reading_char = FALSE;
  1402. X        /*--------------------------------------
  1403. X         *   Check for normal function keys first.
  1404. X         *--------------------------------------*/
  1405. X        ambiguous = FALSE;
  1406. X        for (cpp = K; cpp < &K[NFKEYS]; cpp++) {
  1407. X            if (*cpp == NULL)
  1408. X                continue;
  1409. X            if (strcmp(*cpp, buf) == 0)
  1410. X                return (KEY) (cpp - K + KFIRST);
  1411. X            if (strncmp(*cpp, buf, l) == 0) {
  1412. X                ambiguous = TRUE;
  1413. X                break;
  1414. X                }
  1415. X            }
  1416. X        /*--------------------------------------
  1417. X         *   Check for multiple characters key
  1418. X         *   sequences.
  1419. X         *--------------------------------------*/
  1420. X        if (!ambiguous) {
  1421. X            for (key = KFIRST + NFKEYS, lp = ll_first(kp->k_maps); lp; 
  1422. X                key++, lp = ll_next(lp)) {
  1423. X                MAP *mp = (MAP *) ll_elem(lp);
  1424. X                if (strcmp(buf, mp->m_keys) == 0)
  1425. X                    return key;
  1426. X                if (strncmp(buf, mp->m_keys, l) == 0) {
  1427. X                    ambiguous = TRUE;
  1428. X                    ch = 1;    /* Non-zero.    */
  1429. X                    break;
  1430. X                    }
  1431. X                }
  1432. X            }
  1433. X        if (ch == 0 || !ambiguous) {
  1434. X            if (buf[1])
  1435. X                bufptr = &buf[1];
  1436. X            tttimeout(FALSE);
  1437. X            return buf[0];
  1438. X            }
  1439. X        timeout = TRUE;
  1440. X        }
  1441. X    
  1442. X}
  1443. X# endif
  1444. Xinq_command()
  1445. X{
  1446. X    strl_acc_assign(user_call);
  1447. X    return 0;
  1448. X}
  1449. Xexec_key(c)
  1450. X{    register char    *cp;
  1451. X    int    list_flag;
  1452. X    char    *get_key_assignment();
  1453. X
  1454. X    u_chain();
  1455. X    cp = get_key_assignment(c, &list_flag);
  1456. X    character = (char) c;
  1457. X
  1458. X    remember_macro(cp, list_flag);
  1459. X        
  1460. X    if (list_flag) {
  1461. X        LISTV    result;
  1462. X        eval((LIST *) cp, &result);
  1463. X        return 0;
  1464. X        }
  1465. X
  1466. X    if (cp[0] != '_')
  1467. X        strcpy(user_call, cp);
  1468. X    trace_log("\nKEY_EXEC:    %s\n", cp);
  1469. X    return str_exec(cp);
  1470. X}
  1471. Xchar *
  1472. Xget_key_assignment(c, list_flagp)
  1473. Xint *list_flagp;
  1474. X{
  1475. X    register List_p    lp;
  1476. X    register char *cp;
  1477. X    *list_flagp = TRUE;
  1478. X    
  1479. X    if (c >= KFIRST + NFKEYS) {
  1480. X        int    i = c - KFIRST - NFKEYS;
  1481. X        MAP    *mp;
  1482. X        for (lp = ll_first(kp->k_maps); i-- > 0 && lp; )
  1483. X            lp = ll_next(lp);
  1484. X        mp = (MAP *) ll_elem(lp);
  1485. X        cp = mp->m_value;
  1486. X        if (mp->m_flags & K_LIST)
  1487. X            return cp;
  1488. X        }
  1489. X    else if (curbp->b_keyboard) {
  1490. X        cp = curbp->b_keyboard->k_keys[c];
  1491. X        if (curbp->b_keyboard->k_flags[c] & K_LIST)
  1492. X            return cp;
  1493. X        if (cp && strcmp(cp, "nothing") == 0) {
  1494. X            cp = kp->k_keys[c];
  1495. X            if (kp->k_flags[c] & K_LIST)
  1496. X                return cp;
  1497. X            }
  1498. X        }
  1499. X    else {
  1500. X        cp = kp->k_keys[c];
  1501. X        if (kp->k_flags[c] & K_LIST)
  1502. X            return cp;
  1503. X        }
  1504. X    *list_flagp = FALSE;
  1505. X    return cp ? cp : "self_insert";
  1506. X}
  1507. Xinq_keyboard()
  1508. X{
  1509. X    accumulator = kp->k_id;
  1510. X    return 0;
  1511. X}
  1512. Xinq_local_keyboard()
  1513. X{
  1514. X    accumulator = curbp->b_keyboard ? curbp->b_keyboard->k_id : 0;
  1515. X    return 0;
  1516. X}
  1517. Xkbd_push()
  1518. X{    register int    i = argv[1].l_flags == F_NULL ? 0 : (int) argv[1].l_int;
  1519. X    register int    j;
  1520. X
  1521. X    if (i) {
  1522. X        List_p    lp;
  1523. X        for (lp = ll_first(hd_kbd); lp; lp = ll_next(lp)) {
  1524. X            kp = (struct kbd_stk *) ll_elem(lp);
  1525. X            if (kp->k_id == i) {
  1526. X                kp->k_ref++;
  1527. X                break;
  1528. X                }
  1529. X            }
  1530. X        if (lp == NULL) {
  1531. X            for (lp = ll_first(hd_kstk); lp; lp = ll_next(lp)) {
  1532. X                kp = (struct kbd_stk *) ll_elem(lp);
  1533. X                if (kp->k_id == i) {
  1534. X                    ll_delete(lp);
  1535. X                    break;
  1536. X                    }
  1537. X                }
  1538. X            }
  1539. X        if (lp == NULL)
  1540. X            errorf("keyboard_push: %d not found.", i);
  1541. X        }
  1542. X    else {
  1543. X        kp = (struct kbd_stk *) chk_alloc(sizeof (struct kbd_stk));
  1544. X        kp->k_id = kid++;
  1545. X        kp->k_maps = ll_init();
  1546. X        for (j = 0; j < NKEYS; j++) {
  1547. X            kp->k_keys[j] = i ? (char *) NULL : "nothing";
  1548. X            kp->k_flags[j] = 0;
  1549. X            }
  1550. X        }
  1551. X    ll_push(hd_kbd, (char *) kp);
  1552. X
  1553. X    return 0;
  1554. X    
  1555. X}
  1556. Xkbd_pop()
  1557. X{    int    i = argv[1].l_flags == F_NULL ? 0 : (int) argv[1].l_int;
  1558. X    register int    j;
  1559. X    List_p lp = ll_first(hd_kbd);
  1560. X
  1561. X    if (lp == NULL)
  1562. X        return 0;
  1563. X    kp = (struct kbd_stk *) ll_elem(lp);
  1564. X    (void) ll_pop(hd_kbd);
  1565. X
  1566. X    if (i == 0) {
  1567. X        if (--kp->k_ref <= 0) {
  1568. X            for (j = 0; j < NKEYS; j++)
  1569. X                if (kp->k_keys[j] && kp->k_flags[j] & K_ALLOC)
  1570. X                    chk_free(kp->k_keys[j]);
  1571. X            for (lp = ll_first(kp->k_maps); lp; 
  1572. X                lp = ll_next(lp)) {
  1573. X                MAP    *mp = (MAP *) ll_elem(lp);
  1574. X                chk_free(mp->m_keys);
  1575. X                chk_free(mp->m_value);
  1576. X                }
  1577. X            ll_clear(kp->k_maps);
  1578. X            ll_free(kp->k_maps);
  1579. X            chk_free((char *) kp);
  1580. X            }
  1581. X        }
  1582. X    else {
  1583. X        ll_append(hd_kstk, (char *) kp);
  1584. X        }
  1585. X    lp = ll_first(hd_kbd);
  1586. X    kp = lp ? (struct kbd_stk *) ll_elem(lp) : NULL;
  1587. X
  1588. X    return 0;
  1589. X}
  1590. Xuse_local_keyboard()
  1591. X{
  1592. X    struct    kbd_stk    *kp;
  1593. X    register List_p    lp;
  1594. X
  1595. X    accumulator = 0;
  1596. X    if (argv[1].l_int == 0) {
  1597. X        curbp->b_keyboard = NULL;
  1598. X        return 0;
  1599. X        }
  1600. X    for (lp = ll_first(hd_kstk); lp; lp = ll_next(lp)) {
  1601. X        kp = (struct kbd_stk *) ll_elem(lp);
  1602. X        if (kp->k_id == argv[1].l_int) {
  1603. X            curbp->b_keyboard = kp;
  1604. X            return 0;
  1605. X            }
  1606. X        }
  1607. X    accumulator = -1;
  1608. X    return 0;
  1609. X}
  1610. Xinq_assignment()
  1611. X{    char    *cp;
  1612. X    short    key;
  1613. X    int    from_key = argv[2].l_flags == F_NULL || argv[2].l_int == 0;
  1614. X
  1615. X    if (from_key) {
  1616. X        if (argv[1].l_flags == F_INT)
  1617. X            key = argv[1].l_int;
  1618. X        else
  1619. X            key = akeytoi(get_str(1));
  1620. X        if (key >= 0) {
  1621. X            if (curbp->b_keyboard) {
  1622. X                cp = curbp->b_keyboard->k_keys[key];
  1623. X                if (cp && strcmp(cp, "nothing") == 0)
  1624. X                    cp = kp->k_keys[key];
  1625. X                }
  1626. X            else 
  1627. X                cp = kp->k_keys[key];
  1628. X            }
  1629. X        else
  1630. X            cp = "nothing";
  1631. X        if (cp == NULL) {
  1632. X            character = (char) key;
  1633. X            cp = "self_insert";
  1634. X            }
  1635. X        strl_acc_assign(cp);
  1636. X        return 0;
  1637. X        }
  1638. X    str_acc_assign("", 0);
  1639. X    if (curbp->b_keyboard)
  1640. X        find_assignment(curbp->b_keyboard->k_keys);
  1641. X    find_assignment(kp->k_keys);
  1642. X
  1643. X    if (saccumulator[0] == NULL)
  1644. X        strl_acc_assign("nothing", 7);
  1645. X    return 0;
  1646. X}
  1647. Xfind_assignment(cpp)
  1648. Xregister char    **cpp;
  1649. X{    char    buf[BUFSIZ];
  1650. X    char    *sp;
  1651. X    short    key;
  1652. X    char    *str1 = get_str(1);
  1653. X
  1654. X    strcpy(buf, saccumulator);
  1655. X    sp = buf + strlen(buf);
  1656. X
  1657. X    for (key = 0; key < NKEYS; key++, cpp++) {
  1658. X        if (*cpp && strcmp(*cpp, str1) == 0) {
  1659. X            if (sp != buf) {
  1660. X                strcpy(sp, "<-also>");
  1661. X                sp += 7;
  1662. X                }
  1663. X            strcpy(sp, aitokey(key));
  1664. X            sp += strlen(sp);
  1665. X            }
  1666. X        }
  1667. X    strl_acc_assign(buf);
  1668. X}
  1669. X# undef    PLUS
  1670. X# undef MINUS
  1671. X# define    CTRL    0x0100
  1672. X# define    SHIFT    0x0200
  1673. X# define    ALT    0x0400
  1674. X# define    KEYPAD    0x0800
  1675. X
  1676. X# define    ALL    (CTRL|SHIFT|ALT|KEYPAD)
  1677. X
  1678. X# define    UP    210
  1679. X# define    DOWN    204
  1680. X# define    LEFT    206
  1681. X# define    RIGHT    208
  1682. X# define    HOME    209
  1683. X# define    END    203
  1684. X# define    PGUP    211
  1685. X# define    PGDN    205
  1686. X# define    STAR    42
  1687. X# define    MINUS    169
  1688. X# define    PLUS    168
  1689. X# define    DEL    152
  1690. X# define    INS    KEY_0
  1691. X/*
  1692. X# define    F1    128
  1693. X# define    F2    129
  1694. X# define    F3    130
  1695. X# define    F4    131
  1696. X# define    F5    132
  1697. X# define    F6    133
  1698. X# define    F7    134
  1699. X# define    F8    135
  1700. X# define    F9    136
  1701. X# define    F10    137
  1702. X*/
  1703. X# define    F11    138
  1704. X# define    F12    139
  1705. X# define    BACKSPACE    8
  1706. X# define    ENTER    '\r'
  1707. Xstruct map {
  1708. X    int    len;
  1709. X    char    *name;
  1710. X    short    value;
  1711. X    };
  1712. Xstruct map    special[] = {
  1713. X    {0, "<Ctrl-Home>",        223},
  1714. X    {0, "<Ctrl-End>",        217},
  1715. X    {0, "<Ctrl-PgUp>",        225},
  1716. X    {0, "<Ctrl-PgDn>",        219},
  1717. X    {0, "<Ctrl-Left arrow>",    220},
  1718. X    {0, "<Ctrl-Right arrow>",    222},
  1719. X    {0, "<Ins>",        KEY_0},
  1720. X    {0, "<Del>",        212},
  1721. X    {0, "<Delete>",        127},
  1722. X    {0, "<Keypad-plus>",    213},
  1723. X    {0, "<Keypad-minus>",    214},
  1724. X    {0, "<Keypad-star>",    215},
  1725. X    {0}
  1726. X    };
  1727. X
  1728. Xstruct    map    stoi[] = {
  1729. X    {3, "ESC",        0x1b},
  1730. X    {1, "{",        '{'},
  1731. X    {1, "}",        '}'},
  1732. X    {5, "SPACE",        ' '},
  1733. X    {5, "ENTER",        ENTER},
  1734. X    {3, "TAB",        0x09},
  1735. X    {5, "ARROW",        0},
  1736. X    {4, "CTRL",        CTRL},
  1737. X    {5, "SHIFT",        SHIFT},
  1738. X    {3, "ALT",        ALT},
  1739. X    {6, "KEYPAD",        KEYPAD},
  1740. X    {4, "GREY",        KEYPAD},
  1741. X    {2, "UP",        UP},
  1742. X    {4, "DOWN",        DOWN},
  1743. X    {4, "LEFT",        LEFT},
  1744. X    {5, "RIGHT",        RIGHT},
  1745. X    {4, "HOME",        HOME},
  1746. X    {3, "END",        END},
  1747. X    {4, "PGUP",        PGUP},
  1748. X    {4, "PGDN",        PGDN},
  1749. X    {4, "STAR",        STAR},
  1750. X    {5, "MINUS",        MINUS},
  1751. X    {4, "PLUS",        PLUS},
  1752. X    {3, "DEL",        DEL},
  1753. X    {3, "INS",        INS},
  1754. X    {3, "F12",        F12},
  1755. X    {3, "F11",        F11},
  1756. X    {3, "F10",        F10},
  1757. X    {2, "F9",        F9},
  1758. X    {2, "F8",        F8},
  1759. X    {2, "F7",        F7},
  1760. X    {2, "F6",        F6},
  1761. X    {2, "F5",        F5},
  1762. X    {2, "F4",        F4},
  1763. X    {2, "F3",        F3},
  1764. X    {2, "F2",        F2},
  1765. X    {2, "F1",        F1},
  1766. X    {9, "BACKSPACE",    BACKSPACE},
  1767. X    0
  1768. X    };
  1769. Xchar *
  1770. Xaitokey(key)
  1771. Xshort key;
  1772. X{
  1773. X    struct map *mp;
  1774. X    static char buf[32];
  1775. X    register char *cp;
  1776. X    int    alpha_cnt = 0;
  1777. X
  1778. X    if (key >= ALT_A && key <= ALT_Z) {
  1779. X        sprintf(buf, "<Alt-%c>", key - ALT_A + 'A');
  1780. X        return buf;
  1781. X        }
  1782. X    if (key >= SHIFT_F1 && key <= SHIFT_F1+11) {
  1783. X        sprintf(buf, "<Shift-F%d>", key - SHIFT_F1 + 1);
  1784. X        return buf;
  1785. X        }
  1786. X    if (key >= CTRL_F1 && key <= CTRL_F1+11) {
  1787. X        sprintf(buf, "<Ctrl-F%d>", key - CTRL_F1 + 1);
  1788. X        return buf;
  1789. X        }
  1790. X    if (key >= ALT_F1 && key <= ALT_F1+11) {
  1791. X        sprintf(buf, "<Alt-F%d>", key - ALT_F1 + 1);
  1792. X        return buf;
  1793. X        }
  1794. X    if (key >= ALT_0 && key <= ALT_0+9) {
  1795. X        sprintf(buf, "<Alt-%d>", key - ALT_0);
  1796. X        return buf;
  1797. X        }
  1798. X    if (key == BACK_TAB)
  1799. X        return "<Shift-Tab>";
  1800. X
  1801. X    for (mp = special; mp->name; mp++)
  1802. X        if (mp->value == key)
  1803. X            return mp->name;
  1804. X
  1805. X    for (mp = stoi; mp->name; mp++)
  1806. X        if (mp->value == (short) (key & 0xff)) {
  1807. X            sprintf(buf, "<%s>", mp->name);
  1808. X            for (cp = buf; *cp; cp++)
  1809. X                if (*cp >= 'A' && *cp <= 'Z')
  1810. X                    if (alpha_cnt++)
  1811. X                        *cp += 0x20;
  1812. X            return buf;
  1813. X            }
  1814. X    if (key < ' ')
  1815. X        sprintf(buf, "<Ctrl-%c>", key + 'A' - 1);
  1816. X    else
  1817. X        sprintf(buf, "#%d", key);
  1818. X    return buf;
  1819. X}
  1820. X            
  1821. Xnew_akeytoi(string)
  1822. Xchar    *string;
  1823. X{    char    str[80];
  1824. X    register char    *cp;
  1825. X    int    flags = 0;
  1826. X    int    ch;
  1827. X    register struct map *mp;
  1828. X
  1829. X    strcpy(str, string+1);
  1830. X    for (cp = str; *cp; cp++)
  1831. X        if (islower(*cp))
  1832. X            *cp = toupper(*cp);
  1833. X
  1834. X    for (cp = str; *cp && *cp != '>'; ) {
  1835. X        if (*cp == ' ' || *cp == '-' || *cp == '\t') {
  1836. X            cp++;
  1837. X            continue;
  1838. X            }
  1839. X        for (mp = stoi; mp->name; mp++)
  1840. X            if (strncmp(mp->name, cp, mp->len) == 0) {
  1841. X                cp += mp->len;
  1842. X                flags |= mp->value;
  1843. X                break;
  1844. X                }
  1845. X        if (mp->name == 0) {
  1846. X            flags |= *cp;
  1847. X            break;
  1848. X            }
  1849. X        }
  1850. X    ch = flags & 0xff;
  1851. X    switch (flags & ALL) {
  1852. X        case 0:        return ch;
  1853. X        case SHIFT:
  1854. X            if (ch >= F1 && ch <= F12)
  1855. X                return ch + 12;
  1856. X            if (ch >= 'A' && ch <= 'Z')
  1857. X                return ch - 0x20;
  1858. X            if (ch == UP || ch == DOWN || ch == LEFT || ch == RIGHT)
  1859. X                return 0;
  1860. X            if (ch == '\t')
  1861. X                return BACK_TAB;
  1862. X            if (isdigit(ch))
  1863. X                return 0;
  1864. X            return ch;
  1865. X        case CTRL:
  1866. X            if (ch == ENTER)
  1867. X                return '\n';
  1868. X            if (ch >= F1 && ch <= F12)
  1869. X                return ch + 24;
  1870. X            if (ch >= 'A' && ch <= 'Z')
  1871. X                return ch & 0x1f;
  1872. X            if (ch == UP || ch == DOWN || ch == LEFT || ch == RIGHT)
  1873. X                return ch + 14;
  1874. X            if (ch == '{' || ch == '}')
  1875. X                return 0;
  1876. X            if (isdigit(ch))
  1877. X                return 0;
  1878. X            return ch;
  1879. X        case ALT:
  1880. X            if (ch >= F1 && ch <= F12)
  1881. X                return ch + 32;
  1882. X            if (ch >= 'A' && ch <= 'Z')
  1883. X                return (ch - 'A') + ALT_A;
  1884. X            if (isdigit(ch))
  1885. X                return (ch - '0') + ALT_0;
  1886. X            return ch;
  1887. X        case KEYPAD:
  1888. X            switch (ch) {
  1889. X            case MINUS:     return 214;
  1890. X            case PLUS:    return 213;
  1891. X            default:
  1892. X                return 0;
  1893. X            }
  1894. X        case SHIFT|KEYPAD:
  1895. X            return 0;
  1896. X        }    
  1897. X    ewprintf("Not decoded - %s", string);
  1898. X    return 0;
  1899. X}
  1900. SHAR_EOF
  1901. chmod 0444 ./ttykbd.c || echo "restore of ./ttykbd.c fails"
  1902. mkdir . >/dev/null 2>&1
  1903. echo "x - extracting ./undo.c (Text)"
  1904. sed 's/^X//' << 'SHAR_EOF' > ./undo.c &&
  1905. X/**************************************************************
  1906. X *
  1907. X *    CRISP - Custom Reduced Instruction Set Programmers Editor
  1908. X *
  1909. X *    (C) Paul Fox, 1989
  1910. X *    43, Jerome Close          Tel: +44 6284 4222
  1911. X *        Marlow
  1912. X *         Bucks.
  1913. X *        England SL7 1TX
  1914. X *
  1915. X *
  1916. X *    Please See COPYRIGHT notice.
  1917. X *
  1918. X *   Code to implement the undo and redo facilities.
  1919. X **************************************************************/
  1920. X# include    "list.h"
  1921. XSCCSID("@(#) undo.c 1.14, (C) 1989, P. Fox");
  1922. Xstatic void    re_goto();
  1923. Xstatic void    u_write();
  1924. Xstatic undo_check();
  1925. X
  1926. Xenum    undo_opcodes {
  1927. X    GOTO    = 0,
  1928. X    INSERT    = 1,
  1929. X    DELETE    = 2,
  1930. X    RAISE    = 3,
  1931. X    DROP    = 4,
  1932. X    SCRAP    = 5,    /* Operation should do an undo on the scrap */
  1933. X            /* buffer.                    */
  1934. X    };
  1935. X
  1936. Xextern    long    ftell();
  1937. Xextern    char    *mktemp();
  1938. Xextern    doing_selfinsert;
  1939. Xstatic read_last_undo();
  1940. Xstatic    int    undoing_scrap = FALSE;    /* If TRUE stops us printing     */
  1941. X                    /* 'Undone.' twice.        */
  1942. XFILE    *ufp = NULL;
  1943. Xenum undo_state {
  1944. X    NORMAL,
  1945. X    REDO,
  1946. X    UNDO
  1947. X    } undo_state = NORMAL;
  1948. X
  1949. Xstruct undo {
  1950. X    enum undo_opcodes    u_opcode;
  1951. X    int    u_line;
  1952. X    int    u_col;
  1953. X    ANCHOR    u_anchor;
  1954. X    RSIZE    u_length;
  1955. X    long    u_last1;        /* Used for backing up over (write_buffer) */
  1956. X                    /* mark.                */
  1957. X    long    u_last;            /* tell() position of previous undo */
  1958. X    int    u_chain;        /* Non-zero if part of a single        */
  1959. X                    /* undo.                */
  1960. X    };
  1961. Xchar    *u_fname;
  1962. Xint    u_atend = FALSE;        /* If TRUE dont fseek to eof.    */
  1963. Xvoid
  1964. Xu_init()
  1965. X{    char    temp_file[64];
  1966. X    char    *get_tmpdir();
  1967. X    char    *sys_delim();
  1968. X
  1969. X    sprintf(temp_file, "%s%sundoXXXXXX", get_tmpdir(), sys_delim());
  1970. X    u_fname = mktemp(temp_file);
  1971. X    
  1972. X    if ((ufp = fopen(u_fname, "w+")) == NULL) {
  1973. X        printf("Cannot create undo file:\n");
  1974. X        perror(u_fname);
  1975. X        gr_exit();
  1976. X        }
  1977. X    /*-------------------------*/
  1978. X    /* Ensure ftell(ufp) != 0) */
  1979. X    /*-------------------------*/
  1980. X    fwrite("Undo", 4, 1, ufp);
  1981. X    unlink(u_fname);
  1982. X}
  1983. Xchar *
  1984. Xget_tmpdir()
  1985. X{    extern char *ggetenv();
  1986. X    char *cp;
  1987. X    
  1988. X    if ((cp = ggetenv("BTMP")) != NULL)
  1989. X        return cp;
  1990. X    if ((cp = ggetenv("TMP")) != NULL)
  1991. X        return cp;
  1992. X# if defined(VMS)
  1993. X    return "[-]";
  1994. X# else
  1995. X    return "/tmp";
  1996. X# endif
  1997. X}
  1998. Xvoid
  1999. Xu_close()
  2000. X{
  2001. X    if (ufp)
  2002. X        unlink(u_fname);
  2003. X}
  2004. Xvoid
  2005. Xu_insert(n)
  2006. XRSIZE    n;
  2007. X{    register LINE    *clp;
  2008. X    register int    cbo;
  2009. X    register int    line;
  2010. X    struct undo undo_buf;
  2011. X
  2012. X    if (n == 0 || undo_check())
  2013. X        return;
  2014. X
  2015. X    if (undo_state == NORMAL)
  2016. X        curbp->b_nummod++;
  2017. X    undo_buf.u_opcode = INSERT;
  2018. X    undo_buf.u_length = n;
  2019. X
  2020. X    u_write(&undo_buf);
  2021. X
  2022. X    line = *cur_line;
  2023. X    cbo = current_offset(*cur_col, FALSE);
  2024. X    for ( ; line < curbp->b_numlines && n > 0; line++, cbo = 0) {
  2025. X        RSIZE    x,w;
  2026. X        clp = vm_lock_line(line);
  2027. X        x = llength(clp) - cbo;
  2028. X        w = x;
  2029. X        if (x >= n)
  2030. X            w = n;
  2031. X        fwrite(<ext(clp)[cbo], (int) w, 1, ufp);
  2032. X        vm_unlock(line);
  2033. X        if (n -= w) {
  2034. X            fputc('\n', ufp);
  2035. X            n--;
  2036. X            }
  2037. X        }
  2038. X
  2039. X
  2040. X}
  2041. Xvoid
  2042. Xu_delete(n)
  2043. XRSIZE    n;
  2044. X{    struct undo undo_buf1;
  2045. X    struct undo undo_buf;
  2046. X    undo_info *up;
  2047. X    
  2048. X    if (n == 0 || undo_check())
  2049. X        return;
  2050. X    up = undo_state == UNDO ? &curbp->b_redo : &curbp->b_undo;
  2051. X    if (doing_selfinsert && up->u_last) {
  2052. X        if (read_last_undo(&undo_buf1, up))
  2053. X            goto normal;
  2054. X        if (undo_buf1.u_opcode == DELETE) {
  2055. X            extern char character;
  2056. X# ifdef    DEBUG
  2057. X            {char buf[128];
  2058. X            extern int dflag;
  2059. X            if (dflag & DB_UNDO) {
  2060. X                sprintf(buf, 
  2061. X                    "undo(COLLAPSING, %d + %d => %d)\n",
  2062. X                    undo_buf1.u_length, n, 
  2063. X                    undo_buf1.u_length + n);
  2064. X                trace_log(buf, (char *) NULL);
  2065. X                }
  2066. X            }
  2067. X# endif
  2068. X            if ((isalnum(curbp->b_uchar) && isalnum(character)) ||
  2069. X                (isspace(curbp->b_uchar) && isspace(character)) ||
  2070. X                (curbp->b_uchar == 0x1B || character == 0x1B) ||
  2071. X                (ispunct(curbp->b_uchar) && ispunct(character))) {
  2072. X                undo_buf1.u_length += n;
  2073. X                if (!u_atend)
  2074. X                    fseek(ufp, up->u_last, 0);
  2075. X                fwrite((char *) &undo_buf1, sizeof undo_buf1, 1, ufp);
  2076. X                fseek(ufp, 0l, 2);
  2077. X                u_atend = TRUE;
  2078. X                return;
  2079. X                }
  2080. X            }
  2081. X        }
  2082. Xnormal:
  2083. X    if (undo_state == NORMAL)
  2084. X        curbp->b_nummod++;
  2085. X    undo_buf.u_opcode = DELETE;
  2086. X    undo_buf.u_length = n;
  2087. X    u_write(&undo_buf);
  2088. X
  2089. X}
  2090. Xvoid
  2091. Xu_chain()
  2092. X{    extern int playing_back;
  2093. X    if (!playing_back) {
  2094. X        curbp->b_undo.u_chain = 0;
  2095. X        curbp->b_redo.u_chain = 0;
  2096. X        }
  2097. X}
  2098. Xvoid
  2099. Xu_terminate()
  2100. X{
  2101. X    undo_info *up = undo_state == NORMAL ? &curbp->b_undo : &curbp->b_redo;
  2102. X    
  2103. X    up->u_last1 = up->u_last;
  2104. X    up->u_last = 0;
  2105. X}
  2106. Xvoid
  2107. Xu_dot()
  2108. X{    struct undo undo_buf;
  2109. X
  2110. X    if (undo_check())
  2111. X        return;
  2112. X    undo_buf.u_opcode = GOTO;
  2113. X    u_write(&undo_buf);
  2114. X}
  2115. X
  2116. Xvoid
  2117. Xu_raise()
  2118. X{    struct undo undo_buf;
  2119. X    if (undo_check())
  2120. X        return;
  2121. X    undo_buf.u_opcode = RAISE;
  2122. X    u_write(&undo_buf);
  2123. X}
  2124. Xvoid
  2125. Xu_drop()
  2126. X{    struct undo undo_buf;
  2127. X
  2128. X    if (undo_check())
  2129. X        return;
  2130. X
  2131. X    undo_buf.u_opcode = DROP;
  2132. X
  2133. X    undo_buf.u_anchor = *curbp->b_anchor;
  2134. X    u_write(&undo_buf);
  2135. X}
  2136. Xvoid
  2137. Xu_scrap()
  2138. X{    struct undo undo_buf;
  2139. X
  2140. X    if (undo_check())
  2141. X        return;
  2142. X    undo_buf.u_opcode = SCRAP;
  2143. X    u_write(&undo_buf);
  2144. X        
  2145. X}
  2146. X/* Undo utility routines. */
  2147. Xstatic
  2148. Xundo_check()
  2149. X{
  2150. X    if (/*undo_state == REDO || */curbp->b_system || ufp == NULL)
  2151. X        return TRUE;
  2152. X    /*----------------------------------------
  2153. X    /*   If user isn't undoing an undo
  2154. X    /*   then terminate the redo chain so we
  2155. X    /*   dont confuse user.
  2156. X    /*----------------------------------------*/
  2157. X    if (undo_state == NORMAL)
  2158. X        curbp->b_redo.u_last = 0;
  2159. X    return FALSE;
  2160. X}
  2161. Xstatic void
  2162. Xu_write(undop)
  2163. Xstruct undo *undop;
  2164. X{    undo_info *up;
  2165. X
  2166. X    if (undo_state == UNDO)
  2167. X        up = &curbp->b_redo;
  2168. X    else
  2169. X        up = &curbp->b_undo;
  2170. X        
  2171. X    undop->u_line = *cur_line;
  2172. X    undop->u_col = *cur_col;
  2173. X    undop->u_last1 = up->u_last1;
  2174. X    undop->u_last = up->u_last;
  2175. X    undop->u_chain = up->u_chain++;
  2176. X    if (!u_atend)
  2177. X        fseek(ufp, 0l, 2);
  2178. X    up->u_last = ftell(ufp);
  2179. X
  2180. X    u_debug(undop, undo_state == NORMAL ? "normal" :
  2181. X            undo_state == UNDO ? "undo" : "redo");
  2182. X    fwrite((char *) undop, sizeof *undop, 1, ufp);
  2183. X    u_atend = TRUE;
  2184. X}
  2185. Xu_debug(undop, str)
  2186. Xstruct undo *undop;
  2187. Xchar    *str;
  2188. X{
  2189. X# ifdef    DEBUG
  2190. X    char buf[128];
  2191. X    extern int dflag;
  2192. X    if (dflag & DB_UNDO) {
  2193. X        sprintf(buf, 
  2194. X    "%s(%s, line=%d, col=%d, len=%ld, last=%08lx, chain=%d)\n", str,
  2195. X            undop->u_opcode == GOTO ? "GOTO" :
  2196. X            undop->u_opcode == INSERT ? "INSERT" :
  2197. X            undop->u_opcode == DELETE ? "DELETE" :
  2198. X            undop->u_opcode == RAISE ? "RAISE" :
  2199. X            undop->u_opcode == DROP ? "DROP" : 
  2200. X            undop->u_opcode == SCRAP ? "SCRAP" : "??",
  2201. X            undop->u_line, undop->u_col,
  2202. X            undop->u_length, undop->u_last, undop->u_chain);
  2203. X        trace_log(buf, (char *) NULL);
  2204. X        }
  2205. X# endif
  2206. X}
  2207. Xundo()
  2208. X{    int    undo_mod = argv[1].l_flags == F_INT ? argv[1].l_int : 0;
  2209. X    int    past_mark = argv[2].l_flags == F_INT ? argv[2].l_int : 0;
  2210. X    long    num = -1;
  2211. X    static int sub_undo();
  2212. X    struct undo undo_buf;
  2213. X    enum undo_state    saved_undo_state = undo_state;
  2214. X    int    redo = argv[3].l_flags == F_INT;
  2215. X    undo_info *up = redo ? &curbp->b_redo : &curbp->b_undo;
  2216. Xtrace_log(redo ? "doing redo\n" : "doing undo\n", (char *) NULL);
  2217. X    if (up->u_last == 0 && past_mark) {
  2218. X        up->u_last = up->u_last1;
  2219. X        up->u_last1 = 0;
  2220. X        }
  2221. X    undo_state = redo ? REDO : UNDO;
  2222. X    do {
  2223. X        if (sub_undo(&undo_buf, redo, up)) {
  2224. X            undo_state = NORMAL;
  2225. X            return;
  2226. X            }
  2227. X        if (num < 0 && undo_buf.u_chain > 2)
  2228. X            ewprintf("Undoing command...");
  2229. X        if (num < 0)
  2230. X            num = undo_buf.u_chain;
  2231. X        else if (num && undo_buf.u_chain)
  2232. X            percentage(num - undo_buf.u_chain, num, "Undoing", "command");
  2233. X        if (undo_mod && 
  2234. X            (undo_buf.u_opcode != INSERT &&
  2235. X             undo_buf.u_opcode != DELETE))
  2236. X            undo_buf.u_chain = 1;
  2237. X        }
  2238. X    while (undo_buf.u_chain);
  2239. X    undo_state = saved_undo_state;
  2240. X    if (!undoing_scrap)
  2241. X        ewprintf(redo ? "Redone." : "Undone.");
  2242. X    return;
  2243. X}
  2244. Xstatic
  2245. Xsub_undo(undop, redo, up)
  2246. Xstruct undo *undop;
  2247. Xundo_info *up;
  2248. X{    long pos;
  2249. X    char    buf[64];
  2250. X    int    n;
  2251. X
  2252. X    if (up->u_last == 0) {
  2253. X        ewprintf("Nothing to %s.", redo ? "redo" : "undo");
  2254. X        curbp->b_flag &= ~BFCHG;
  2255. X        return -1;
  2256. X        }
  2257. X    if (read_last_undo(undop, up))
  2258. X        return -1;
  2259. X    u_debug(undop, "UNDOING");
  2260. X    up->u_last = undop->u_last;
  2261. X    up->u_last1 = undop->u_last1;
  2262. X    switch (undop->u_opcode) {
  2263. X      case INSERT:
  2264. SHAR_EOF
  2265. echo "End of part 10"
  2266. echo "File ./undo.c is continued in part 11"
  2267. echo "11" > s2_seq_.tmp
  2268. exit 0
  2269. -- 
  2270. =====================            Reuters Ltd PLC, 
  2271. Tel: +44 628 891313 x. 212         Westthorpe House,
  2272. UUCP:     fox%marlow.uucp@idec.stc.co.uk  Little Marlow,
  2273.                        Bucks, England SL7 3RQ
  2274.  
  2275.