home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / gnu / pdksh-src.lha / src / amiga / pdksh / sh / edit.c < prev    next >
C/C++ Source or Header  |  1993-12-01  |  9KB  |  479 lines

  1. /*
  2.  * Command line editing - common code
  3.  *
  4.  */
  5.  
  6. #include "config.h"
  7. #if defined(EMACS) || defined(VI)
  8.  
  9. #ifndef lint
  10. static char *RCSid = "$Id: edit.c,v 1.4 1992/05/12 09:30:31 sjg Exp $";
  11. #endif
  12.  
  13. #include "stdh.h"
  14. #include <unistd.h>
  15. #include <signal.h>
  16. #include <fcntl.h>
  17. #include <errno.h>
  18. #include <setjmp.h>
  19. #ifndef NOSTDHDRS
  20. # include <string.h>
  21. #endif
  22. #include "sh.h"
  23. #include "tty.h"
  24. #define EXTERN
  25. #include "edit.h"
  26. #undef EXTERN
  27.  
  28. #ifdef _CRAY2
  29. extern unsigned    sleep();
  30. #endif
  31.  
  32.  
  33. static int    x_noecho = 0;
  34.  
  35. /*
  36.  * read an edited command line
  37.  */
  38. int
  39. x_read(fd, buf, len)
  40.     int fd;            /* not used */
  41.     char *buf;
  42.     size_t len;
  43. {
  44.   static int setup_done = 0;
  45.     int    i;
  46.  
  47.   if (setup_done != 42)
  48.   {
  49.     setup_done = 42;        /* these get done once only */
  50.     x_do_init = 1;
  51.     x_cols = 80;
  52.     x_col = 0;
  53.     ed_erase = -1, ed_kill = -1, ed_werase = -1, ed_intr = -1, ed_quit = -1;
  54.     x_adj_ok = 1;
  55.     x_adj_done = 0;
  56.   }
  57.     if (x_do_init)
  58.         x_init();
  59.  
  60.     if (x_noecho)
  61. #ifdef amigados
  62.         return(tty_read(ttyfd, buf, len));
  63. #else
  64.         return(read(ttyfd, buf, len));
  65. #endif
  66.  
  67.     (void)x_mode(TRUE);
  68. #ifdef EMACS
  69.     if (flag[FEMACS])
  70.         i = x_emacs(buf, len);
  71.     else
  72. #endif
  73. #ifdef VI
  74.     if (flag[FVI])
  75.         i = x_vi(buf, len);
  76.     else
  77. #endif
  78.         i = -1;        /* internal error */
  79.     (void) x_mode(FALSE);
  80.     if (i > 4 && strstr(buf, "stty"))
  81.         x_do_init = 1;
  82.     if (i < 0 && errno == EINTR)
  83.         trapsig(SIGINT);
  84.     return i;
  85. }
  86.  
  87. /* tty I/O */
  88.  
  89. int
  90. x_getc()
  91. {
  92.   char c;
  93.  
  94.   /*
  95.    * This allows the arival of a SIGCHLD to not disturb us until 
  96.    * we are ready. 
  97.    * BSD and other systems that automatically rety a read after 
  98.    * an interrupt don't need this but it doesn't do any harm 
  99.    * either. 
  100.    */
  101.  retry:
  102. #ifdef amigados
  103.     if (tty_read(ttyfd, &c, 1) != 1)
  104. #else
  105.     if (read(ttyfd, &c, 1) != 1)
  106. #endif
  107.     {
  108.       if (sigchld_caught)        /* just a SIGCHLD ? */
  109.       {
  110.         goto retry;
  111.       }
  112.       return -1;
  113.     }
  114.     return c & 0x7F;
  115. }
  116.  
  117. void
  118. x_flush()
  119. {
  120.     fflush(stdout);
  121. }
  122.  
  123.  
  124. /* NAME:
  125.  *      x_adjust - redraw the line adjusting starting point etc.
  126.  *
  127.  * DESCRIPTION:
  128.  *      This function is called when we have exceeded the bounds 
  129.  *      of the edit window.  It increments x_adj_done so that 
  130.  *      functions like x_ins and x_delete know that we have been 
  131.  *      called and can skip the x_bs() stuff which has already 
  132.  *      been done by x_redraw.
  133.  *
  134.  * RETURN VALUE:
  135.  *      None
  136.  */
  137.  
  138. void
  139. x_adjust()
  140. {
  141.   x_adj_done++;            /* flag the fact that we were called. */
  142. #ifdef EMACS
  143.   /*
  144.    * we had a promblem if the prompt length > x_cols / 2
  145.    */
  146.   if ((xbp = xcp - (x_displen / 2)) < xbuf)
  147.     xbp = xbuf;
  148.   xlp_valid = FALSE;
  149.   x_redraw(x_cols);
  150. #endif
  151.   x_flush();
  152. }
  153.  
  154. void
  155. x_putc(c)
  156.     int c;
  157. {
  158.   if (c == '\r' || c == '\n')
  159.     x_col = 0;
  160.   if (x_col < x_cols)
  161.   {
  162.     putc(c, stdout);
  163.     switch(c)
  164.     {
  165.     case BEL:
  166.       break;
  167.     case '\r':
  168.     case '\n':
  169.     break;
  170.     case '\b':
  171.       x_col--;
  172.       break;
  173.     default:
  174.       x_col++;
  175.       break;
  176.     }
  177.   }
  178.   if (x_adj_ok && (x_col < 0 || x_col >= (x_cols - 2)))
  179.   {
  180.     x_adjust();
  181.   }
  182. }
  183.  
  184. #ifdef DEBUG
  185. int
  186. x_debug_info()
  187. {
  188.   x_flush();
  189.   printf("\nksh debug:\n");
  190.   printf("\tx_col == %d,\t\tx_cols == %d,\tx_displen == %d\n",
  191.      x_col, x_cols, x_displen);
  192.   printf("\txcp == 0x%lx,\txep == 0x%lx\n", (long) xcp, (long) xep);
  193.   printf("\txbp == 0x%lx,\txbuf == 0x%lx\n", (long) xbp, (long) xbuf);
  194.   printf("\txlp == 0x%lx\n", (long) xlp);
  195.   printf("\txlp == 0x%lx\n", (long) x_lastcp());
  196.   printf("\n");
  197.   x_redraw(-1);
  198.   return 0;
  199. }
  200. #endif
  201.  
  202. void
  203. x_puts(s)
  204.     register char *s;
  205. {
  206.   register int    adj = x_adj_done;
  207.  
  208.   while (*s && adj == x_adj_done)
  209.     x_putc(*s++);
  210. }
  211.  
  212. #ifdef _BSD
  213. static    struct sgttyb cb, cborig;
  214. #ifdef TIOCGATC
  215. static struct ttychars lchars, lcharsorig;
  216. #else
  217. static struct tchars tchars, tcharsorig;
  218. #ifdef TIOCGLTC
  219. static struct ltchars ltchars, ltcharsorig;
  220. #endif
  221. #endif
  222. #else
  223. static    struct termio cb, cborig;
  224. #endif
  225.  
  226. /* initialize editing mode */
  227. void
  228. x_init()
  229. {
  230.     x_do_init = 0;
  231. #ifdef _BSD
  232.     (void)ioctl(ttyfd, TIOCGETP, &cborig);
  233.     if ((cborig.sg_flags & ECHO) == 0)
  234.         x_noecho = 1;
  235.     cb = cborig;
  236.     ed_erase = cb.sg_erase;
  237.     ed_kill = cb.sg_kill;
  238.     cb.sg_flags &= ~ECHO;
  239.     cb.sg_flags |= CBREAK;
  240. #ifdef TIOCGATC
  241.     (void)ioctl(ttyfd, TIOCGATC, &lcharsorig);
  242.     lchars = lcharsorig;
  243.     ed_werase = lchars.tc_werasc;
  244.     lchars.tc_suspc = -1;
  245.     lchars.tc_dsuspc = -1;
  246.     lchars.tc_lnextc = -1;
  247.     lchars.tc_statc = -1;
  248.     lchars.tc_intrc = -1;
  249.     lchars.tc_quitc = -1;
  250.     lchars.tc_rprntc = -1;
  251. #else
  252.     (void)ioctl(ttyfd, TIOCGETC, &tcharsorig);
  253. #ifdef TIOCGLTC
  254.     (void)ioctl(ttyfd, TIOCGLTC, <charsorig);
  255. #endif
  256.     tchars = tcharsorig;
  257. #ifdef TIOCGLTC
  258.     ltchars = ltcharsorig;
  259.     ed_werase = ltchars.t_werasc;
  260.     ltchars = ltcharsorig;
  261.     ltchars.t_suspc = -1;
  262.     ltchars.t_dsuspc = -1;
  263.     ltchars.t_lnextc = -1;
  264. #endif
  265.     tchars.t_intrc = -1;
  266.     tchars.t_quitc = -1;
  267. #ifdef TIOCGLTC
  268.     ltchars.t_rprntc = -1;
  269. #endif
  270. #endif
  271. #else /* !_BSD */
  272.     (void)ioctl(ttyfd, TCGETA, &cborig);
  273.     if ((cborig.c_lflag & ECHO) == 0)
  274.         x_noecho = 1;
  275.     cb = cborig;
  276.     ed_erase = cb.c_cc[VERASE]; /* TODO */
  277.     ed_kill = cb.c_cc[VKILL]; /* TODO */
  278.     ed_intr = cb.c_cc[VINTR];
  279.     ed_quit = cb.c_cc[VQUIT];
  280. #ifdef _CRAY2        /* brain-damaged terminal handler */
  281.     cb.c_lflag &= ~(ICANON|ECHO);
  282.     /* rely on print routine to map '\n' to CR,LF */
  283. #else
  284.     cb.c_iflag &= ~(INLCR|ICRNL);
  285. #ifdef _BSD_SYSV    /* need to force CBREAK instead of RAW (need CRMOD on output) */
  286.     cb.c_lflag &= ~(ICANON|ECHO);
  287. #else
  288. #ifdef SWTCH    /* need CBREAK to handle swtch char */
  289.     cb.c_lflag &= ~(ICANON|ECHO);
  290.     cb.c_lflag |= ISIG;
  291.     cb.c_cc[VINTR] = 0377;
  292.     cb.c_cc[VQUIT] = 0377;
  293. #else
  294.     cb.c_lflag &= ~(ISIG|ICANON|ECHO);
  295. #endif
  296. #endif
  297.     cb.c_cc[VTIME] = 0;
  298.     cb.c_cc[VMIN] = 1;
  299. #endif    /* _CRAY2 */
  300. #endif
  301. #ifdef EMACS
  302.     x_emacs_keys(ed_erase, ed_kill, ed_werase, ed_intr, ed_quit);
  303. #endif
  304. }
  305.  
  306. static    bool_t    x_cur_mode = FALSE;
  307.  
  308. /* set/clear tty cbreak mode */
  309.  
  310. #ifdef _BSD
  311. bool_t
  312. x_mode(onoff)
  313.     bool_t    onoff;
  314. {
  315.     bool_t    prev;
  316.  
  317.     if (x_cur_mode == onoff) return x_cur_mode;
  318.     prev = x_cur_mode;
  319.     x_cur_mode = onoff;
  320.     if (onoff)  {
  321.         (void)ioctl(ttyfd, TIOCSETN, &cb);
  322. #ifdef TIOCGATC
  323.         (void)ioctl(ttyfd, TIOCSATC, &lchars);
  324. #else
  325.         (void)ioctl(ttyfd, TIOCSETC, &tchars);
  326. #ifdef TIOCGLTC
  327.         (void)ioctl(ttyfd, TIOCSLTC, <chars);
  328. #endif
  329. #endif
  330.     }
  331.     else {
  332.         (void)ioctl(ttyfd, TIOCSETN, &cborig);
  333. #ifdef TIOCGATC
  334.         (void)ioctl(ttyfd, TIOCSATC, &lcharsorig);
  335. #else
  336.         (void)ioctl(ttyfd, TIOCSETC, &tcharsorig);
  337. #ifdef TIOCGLTC
  338.         (void)ioctl(ttyfd, TIOCSLTC, <charsorig);
  339. #endif
  340. #endif
  341.     }
  342.     return prev;
  343. }
  344.  
  345. #else    /* !_BSD */
  346.  
  347. bool_t
  348. x_mode(onoff)
  349. bool_t    onoff;
  350. {
  351.     bool_t    prev;
  352.  
  353.     if (x_cur_mode == onoff) return x_cur_mode;
  354.     prev = x_cur_mode;
  355.     x_cur_mode = onoff;
  356.  
  357.     if (onoff)  {
  358. #ifndef TCSETAW                /* e.g. Cray-2 */
  359.         /* first wait for output to drain */
  360. #ifdef TCSBRK
  361.         (void)ioctl(ttyfd, TCSBRK, 1);
  362. #else    /* the following kludge is minimally intrusive, but sometimes fails */
  363.         (void)sleep((unsigned)1);    /* fake it */
  364. #endif
  365. #endif
  366. #if defined(_BSD_SYSV) || !defined(TCSETAW)
  367. /* _BSD_SYSV needs to force TIOCSETN instead of TIOCSETP (preserve type-ahead) */
  368.         (void)ioctl(ttyfd, TCSETA, &cb);
  369. #else
  370.         (void)ioctl(ttyfd, TCSETAW, &cb);
  371. #endif
  372.     }
  373.     else {
  374. #ifndef TCSETAW                /* e.g. Cray-2 */
  375.         /* first wait for output to drain */
  376. #ifdef TCSBRK
  377.         (void)ioctl(ttyfd, TCSBRK, 1);
  378. #else
  379. /* doesn't seem to be necessary when leaving xmode */
  380. /*        (void)sleep((unsigned)1);    /* fake it */
  381. #endif
  382. #endif
  383. #if defined(_BSD_SYSV) || !defined(TCSETAW)
  384. /* _BSD_SYSV needs to force TIOCSETN instead of TIOCSETP (preserve type-ahead) */
  385.         (void)ioctl(ttyfd, TCSETA, &cborig);
  386. #else
  387.         (void)ioctl(ttyfd, TCSETAW, &cborig);
  388. #endif
  389.     }
  390.     return prev;
  391. }
  392. #endif    /* _BSD */
  393.  
  394.  
  395. /* NAME:
  396.  *      promptlen - calculate the length of PS1 etc.
  397.  *
  398.  * DESCRIPTION:
  399.  *      This function is based on a fix from guy@demon.co.uk
  400.  *      It fixes a bug in that if PS1 contains '!', the length 
  401.  *      given by strlen() is probably wrong.
  402.  *
  403.  * RETURN VALUE:
  404.  *      length
  405.  */
  406.  
  407. int
  408. promptlen(cp)
  409.   register char  *cp;
  410. {
  411.   register int count = 0;
  412.  
  413.   while (*cp)
  414.   {
  415.     if ( *cp++ != '!' )
  416.       count++;
  417.     else
  418.       if ( *cp == '!' )
  419.       {
  420.     cp++;
  421.     count++;
  422.       }
  423.       else
  424.       {
  425.     register int i = source->line;
  426.  
  427.     do
  428.     {
  429.       count ++;
  430.     }
  431.     while( ( i /= 10 ) > 0 );
  432.       }
  433.   }
  434.   return count;
  435. }
  436.  
  437.  
  438. /*
  439.  * this function check the environment
  440.  * for FCEDIT,EDITOR or VISUAL
  441.  * as a hint to what edit mode is desired.
  442.  */
  443. init_editmode()
  444. {
  445.   static char *ev[] = { "FCEDIT", "EDITOR", "VISUAL", NULL };
  446.   register int i;
  447.   register char *rcp, *rcp2;
  448.  
  449.   for (i = 0; ev[i]; i++)
  450.   {
  451.     if ((rcp = getenv(ev[i])) && *rcp)
  452.       break;
  453.   }
  454.   if (ev[i] && rcp)
  455.   {
  456.     if (rcp2 = strrchr(rcp, '/'))
  457.       rcp = ++rcp2;
  458. #ifdef EMACS
  459.     if (strstr(rcp, "emacs"))
  460.     {
  461.       flag[FVI] = 0;
  462.       flag[FEMACS] = 1;
  463.     }
  464. #endif
  465. #if defined(EMACS) && defined(VI)
  466.     else
  467. #endif
  468. #ifdef VI
  469.       if (strstr(rcp, "vi"))
  470.       {
  471.     flag[FVI] = 1;
  472.     flag[FEMACS] = 0;
  473.       }
  474. #endif
  475.   }
  476.   return 0;
  477. }
  478. #endif
  479.