home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume20 / reactivekbd / part03 / file+rk.c
Encoding:
C/C++ Source or Header  |  1989-10-16  |  20.9 KB  |  827 lines

  1. /* LINTLIBRARY */
  2.  
  3. #include "file+rk.h"        /* JJD 3-89 */
  4. #include "rk_button.h"        /* JJD 9-86 */
  5. #include "functions.h"        /* MLJ 5-89 */
  6. #include <sys/types.h>
  7. #include <sys/time.h>
  8. #include <sys/errno.h>
  9. #include <sys/stat.h>  
  10. #include <signal.h>
  11. #include <sys/wait.h>
  12. #include <sys/ioctl.h>
  13. #include <fcntl.h>
  14. #include <stdio.h>
  15. #include <sys/file.h>
  16. char           *getenv();
  17. #include <pwd.h>
  18.  
  19. /* struct passwd *pwd; */
  20.  
  21. /* Global Variables */
  22.  
  23. extern          errno;
  24.  
  25. int             pty_master, pty_slave, tty;
  26. struct sgttyb   new_stdin, old_stdin;
  27.  
  28. struct sgttyb   pty_sgtty;
  29.  
  30. char            tc_ent[1024], tc_seq_buf[1024], *clear_to_eol;
  31. char           *cursor_left, *cursor_right;
  32. char           *enter_insert_mode, *exit_insert_mode;
  33. char           *pre_insert_char, *post_insert_char;
  34. char           *enter_delete_mode, *exit_delete_mode, *delete_a_char;
  35. char           *clear_screen;
  36. char           *enter_standout_mode, *exit_standout_mode;    /* JJD 9-86 */
  37.  
  38. char            pred_buff[MAX_CMD_LINE_LENGTH];    /* JJD 9-86 */
  39. char            pred_on_display = 0;    /* JJD 9-86 */
  40. char            pred_mode = 1;    /* JJD 9-86 */
  41. int             pred_number = 0;/* JJD 9-86 */
  42. char        show_eol_mode = 1;
  43. char            nl_truncate_mode = 1;    /* JJD 9-86 */
  44. char            eol_only_mode = 1;    /* JJD 9-86 */
  45. char            eol_longer_mode = 1;    /* JJD 9-86 */
  46. char            lisp_mode = 0;
  47. char        add_space_mode = 0;
  48. char        silent=0;
  49. char        login=1;
  50.  
  51. int             (*keymap[128][MAXEXTENSIONS]) ();
  52. char            meta_prefixes[MAXEXTENSIONS][MAXEXTENSIONS];
  53. int        meta_map[MAXEXTENSIONS][MAXEXTENSIONS];
  54. int        current_key_map=0;
  55. char        next_free_map=1;
  56. char           *shellname;
  57.  
  58. ED_STRUCT       editor_data;
  59.  
  60. char            output_string[1024], temp_str[1024];
  61. int             output_string_length;
  62. int         finished=0;
  63. int        childid;
  64.  
  65. int        num_buffers=64;
  66.  
  67.  
  68. void childdied()
  69. {
  70.     union wait      w;
  71.     register int    pid;
  72.  
  73.     while ((pid = wait3(&w, WUNTRACED | WNOHANG, 0)) > 0) {
  74.         if (WIFSTOPPED(w)) {
  75.             fprintf(stderr,"Stopped.\r\n");
  76.         } else if (WIFEXITED(w)) {
  77.         } else if (WIFSIGNALED(w)) {
  78.             fprintf(stderr,"Killed.\r\n");
  79.         }
  80.  
  81.                 /* if this is our shell who died, shut down */
  82.         if(pid==childid){    
  83.             abortit("\r\n",0);
  84.         }
  85.     }
  86.     return;
  87. }
  88.  
  89. void cleanup()
  90. {
  91.     abortit("Segmentation fault, aborting...\n",-1);
  92. }
  93.  
  94.  
  95.  
  96. int READ(d, buf, nbytes)
  97. int d;
  98. char *buf;
  99. int nbytes;
  100. {
  101.     int ret;
  102.     static int count=0;
  103.     
  104.     if((ret=read(d,buf,nbytes))<-1){
  105.         if(errno==EBADF){
  106.             if(count){
  107.                 perror("Read");
  108.                 abortit("",-1);
  109.             } else {
  110.                 count++;
  111.                 sleep(1);  /* wait for the signal */
  112.             }
  113.         } else {
  114.             perror("Read");
  115.             abortit("",-1);
  116.         }
  117.     } else {
  118.         return(ret);
  119.     }
  120. }
  121.  
  122. main(argc, argv)
  123.     int             argc;
  124.     char          *argv[];
  125. {
  126.  
  127.     char           *getenv();    /* JJD 3-89 added */
  128.     get_termcap_stuff();
  129.     get_command_line_arguments(argc,argv);
  130.     set_up_keymap();
  131.     get_key_bindings(); 
  132.     init();
  133.     set_up_buffers();
  134.     file();
  135.     /*NOTREACHED*/
  136.     shutdown_pty_and_tty();
  137.     shutdown_();
  138.     abortit("",1);        /* JJD 3-89 added 1 */
  139. }
  140.  
  141.  
  142. get_termcap_stuff()
  143. {
  144.  
  145.     char           *termname, *tbuf, *getenv(), *tgetstr();
  146.  
  147.     termname = getenv("TERM");
  148.     if (!termname) {
  149.         enter_insert_mode = exit_insert_mode = pre_insert_char =
  150.             post_insert_char = 0;
  151.         enter_delete_mode = exit_delete_mode = delete_a_char = 0;
  152.         cursor_right = 0;
  153.         cursor_left = "\010";
  154.         clear_screen = 0;
  155.         enter_standout_mode = exit_standout_mode = 0;    /* JJD 9-86 */
  156.         return;
  157.     }
  158.     tbuf = tc_seq_buf;
  159.     if (tgetent(tc_ent, termname) != 1) {
  160.         enter_insert_mode = exit_insert_mode = pre_insert_char = 0;
  161.         post_insert_char = enter_delete_mode = exit_delete_mode = 0;
  162.         delete_a_char = cursor_right = clear_screen = 0;
  163.         cursor_left = "\010";
  164.         enter_standout_mode = exit_standout_mode = 0;    /* JJD 9-86 */
  165.         return;
  166.     }
  167.     if (tgetflag("bs"))
  168.         cursor_left = "\010";
  169.     else
  170.         cursor_left = tgetstr("bc", &tbuf);
  171.  
  172.     clear_to_eol = tgetstr("ce", &tbuf);
  173.     cursor_right = tgetstr("nd", &tbuf);
  174.     enter_insert_mode = tgetstr("im", &tbuf);
  175.     exit_insert_mode = tgetstr("ei", &tbuf);
  176.     pre_insert_char = tgetstr("ic", &tbuf);
  177.     post_insert_char = tgetstr("ip", &tbuf);
  178.     enter_delete_mode = tgetstr("dm", &tbuf);
  179.     exit_delete_mode = tgetstr("ed", &tbuf);
  180.     delete_a_char = tgetstr("dc", &tbuf);
  181.     clear_screen = tgetstr("cl", &tbuf);
  182.     enter_standout_mode = tgetstr("so", &tbuf);    /* JJD 9-86 */
  183.     exit_standout_mode = tgetstr("se", &tbuf);    /* JJD 9-86 */
  184.  
  185.     if (!enter_standout_mode || !exit_standout_mode)    /* JJD 9-86 */
  186.         enter_standout_mode = exit_standout_mode = 0;
  187.  
  188.     if (!enter_delete_mode || !exit_delete_mode)
  189.         enter_delete_mode = exit_delete_mode = 0;
  190.  
  191.     if (!enter_insert_mode || !exit_insert_mode)
  192.         enter_insert_mode = exit_insert_mode = 0;
  193. }
  194.  
  195. #define LETTERS "pqr"
  196.  
  197. init()
  198. {
  199.     int             i = 48, c = 0;
  200.     char            buf[100];
  201.     struct sgttyb   master_sgttyb,slave_sgttyb;
  202.     int             pid;
  203.  
  204.  
  205.  
  206.  
  207.     while (--i >= 0) {
  208.         sprintf(buf, "/dev/pty%c%x", LETTERS[c >> 4], c & 15);
  209.         if ((pty_master = open(buf, (O_RDWR | O_EXCL))) != -1)
  210.             break;
  211.         c++;
  212.     }
  213.     if (i <= 0) {
  214.         printf("Unable to open a pty, aborting...\r\n");
  215.         abortit("",-1);
  216.     }
  217.     ioctl(0, TIOCGETP, &old_stdin);
  218.     ioctl(0, TIOCGETP, &new_stdin);
  219.     new_stdin.sg_flags |= (CBREAK|RAW|CRMOD);
  220.     new_stdin.sg_flags &= ~(ECHO);
  221.     ioctl(0, TIOCSETP, &new_stdin);
  222.  
  223.     ioctl(pty_master, TIOCGETP, &master_sgttyb);
  224.     master_sgttyb.sg_flags &= ~(RAW | CBREAK| LCASE);
  225.     master_sgttyb.sg_flags |= (ECHO | CRMOD | FF0);
  226.     master_sgttyb.sg_ospeed = old_stdin.sg_ospeed;
  227.     master_sgttyb.sg_ispeed = old_stdin.sg_ispeed;
  228.     ioctl(pty_master, TIOCSETP, &master_sgttyb);
  229.  
  230.     switch (pid = fork()) {
  231.     case -1:
  232.         perror("Fork");
  233.         abortit("",-1);
  234.         break;
  235.     case 0:
  236.         signal(SIGINT, SIG_DFL);
  237.         signal(SIGQUIT, SIG_DFL);
  238.         if ((tty = open("/dev/tty", O_RDWR)) < 0) {
  239.             perror("/dev/tty");
  240.             abortit("",-1);
  241.         }
  242.         ioctl(tty, TIOCNOTTY, &pid);
  243.         close(tty);
  244.         close(pty_master);
  245.         close(0);
  246.         sprintf(buf, "/dev/tty%c%x", LETTERS[c >> 4], c & 15);
  247.         if ((pty_slave = open(buf, (O_RDWR | O_EXCL))) < 0) {
  248.             perror(buf);
  249.             abortit("",-1);
  250.         }
  251.         dup2(0, 1);
  252.         dup2(0, 2);
  253.         ioctl(0, TIOCGETP, &slave_sgttyb);
  254.         slave_sgttyb.sg_flags &= ~(RAW | CBREAK| LCASE);
  255.         slave_sgttyb.sg_flags |= (ECHO | FF0 | CRMOD );
  256.         slave_sgttyb.sg_ospeed = old_stdin.sg_ospeed;
  257.         slave_sgttyb.sg_ispeed = old_stdin.sg_ispeed;
  258.         ioctl(0, TIOCSETP, &slave_sgttyb);
  259.         pid = getpid();
  260.         if (setpgrp(0, pid) < 0) {
  261.             perror("Setpgrp");
  262.             abortit("",-1);
  263.         }
  264.         ioctl(0, TIOCSPGRP, &pid);
  265.         shellname = (char *)getenv ("SHELL");
  266.         if(!shellname)
  267.             shellname="/bin/csh";
  268.         if(login){
  269.             if (execl(shellname, "-", (char *) 0) < 0) {
  270.                 perror("execl");
  271.                 abortit("",-1);
  272.             }
  273.         } else {
  274.             if (execl(shellname, "csh", (char *) 0) < 0) {
  275.                 perror("execl");
  276.                 abortit("",-1);
  277.             }
  278.         }
  279.             
  280.         break;
  281.  
  282.     default:childid=pid;
  283.         break;
  284.     }
  285. }
  286.  
  287. set_up_buffers()
  288. {
  289.  
  290.     int             num_buffs;
  291.     struct ed_buffs *prev_ptr;
  292.  
  293.     editor_data.current_ed_buff_ptr =
  294.         (struct ed_buffs *) malloc(sizeof(struct ed_buffs));
  295.  
  296.     prev_ptr = editor_data.current_ed_buff_ptr;
  297.     prev_ptr->dot = prev_ptr->string;
  298.     prev_ptr->mark = prev_ptr->string;    /* JJD 3-89 added */
  299.  
  300.     for (num_buffs = num_buffers - 1; num_buffs; --num_buffs) {
  301.         prev_ptr->next_ptr =
  302.             (struct ed_buffs *) malloc(sizeof(struct ed_buffs));
  303.         prev_ptr->next_ptr->prev_ptr = prev_ptr;
  304.         prev_ptr = prev_ptr->next_ptr;
  305.         prev_ptr->dot = prev_ptr->string;
  306.         prev_ptr->mark = prev_ptr->string;    /* JJD 3-89 added */
  307.         *(prev_ptr->dot) = '\0';
  308.     }
  309.  
  310.     prev_ptr->next_ptr = editor_data.current_ed_buff_ptr;
  311.     editor_data.current_ed_buff_ptr->prev_ptr = prev_ptr;
  312.  
  313.     editor_data.current_input_char = '\0';
  314.     editor_data.universal_argument = 1;
  315.     editor_data.current_buffer = editor_data.current_ed_buff_ptr->string;
  316.     editor_data.dot = editor_data.current_buffer;
  317.     /* JJD 3-89 added */
  318.     editor_data.mark = editor_data.current_ed_buff_ptr->mark;
  319.     editor_data.current_buffer[0] = '\0';
  320.     output_string[0] = '\0';
  321.     output_string_length = 0;
  322.     temp_str[0] = '\0';
  323. }
  324.  
  325.  
  326. set_up_keymap()
  327. {
  328.     int x,y;
  329.     char buf[4];
  330.  
  331.     buf[1]=0;
  332.  
  333.     for(y=0;y<MAXEXTENSIONS;y++){
  334.         for(x=0;x<MAXEXTENSIONS;x++){
  335.             meta_prefixes[x][y]=0;
  336.             meta_map[x][y]=0;
  337.         }
  338.     }
  339.  
  340.     for(y=0;y<MAXEXTENSIONS;y++){
  341.         for(x=0;x<128;x++){
  342.             keymap[x][y]=BOGUS;
  343.         }
  344.     }
  345.  
  346.  
  347.  
  348.     bind_to_key("^@",set_mark);/* CTRL-@ or CTRL-sp *//* JJD 3-89 */
  349.        bind_to_key("^A",beginning_of_line);    /* CTRL-A */
  350.     bind_to_key("^B",backward_char);    /* CTRL-B */
  351.     bind_to_key("^C",file_completion);    /* CTRL-C *//* JJD 2-89 */
  352.     bind_to_key("^D",delete_char);    /* CTRL-D */
  353.     bind_to_key("^E",end_of_line);    /* CTRL-E */
  354.     bind_to_key("^F",forward_char);    /* CTRL-F */
  355.     bind_to_key("^G",backspace_word);    /* CTRL-G *//* JJD 2-89 */
  356.     bind_to_key("^H",backspace_char);    /* CTRL-H & backspace key */
  357.     bind_to_key("^I",self_insert);    /* CTRL-I & TAB key       */
  358.     bind_to_key("^J",finish_editing_line);    /* CTRL-J */
  359.     bind_to_key("^K",discard_rest_of_line);    /* CTRL-K */
  360.     bind_to_key("^L",clear_display);    /* CTRL-L */
  361.     bind_to_key("^M",finish_editing_line);    /* CTRL-M */
  362.     bind_to_key("^N",next_line);    /* CTRL-N */
  363.     bind_to_key("^O",previous_pred);    /* CTRL-O *//* JJD 9-86 */
  364.     bind_to_key("^P",previous_line);    /* CTRL-P */
  365.     bind_to_key("^Q",accept_forward_char);    /* CTRL-Q *//* JJD 9-86 */
  366.     bind_to_key("^R",next_pred);    /* CTRL-R *//* JJD 9-86 */
  367.     bind_to_key("^S",accept_to_end_of_line);    /* CTRL-S *//* JJD 9-86 */
  368.     bind_to_key("^T",twiddle_chars);    /* CTRL-T */
  369.     bind_to_key("^U",increment_universal_argument);    /* CTRL-U */
  370.     bind_to_key("^V",quote_char);    /* CTRL-V *//* JJD 9-86 */
  371.     bind_to_key("^W",accept_forward_word);    /* CTRL-W *//* JJD 9-86 */
  372.     bind_to_key("^X",show_mark);    /* CTRL-X *//* JJD 3-89 */
  373.     bind_to_key("^Y",yank_from_kill_buffer);    /* CTRL-Y */
  374.     bind_to_key("^Z",insert_suspend_char);    /* CTRL-Z */
  375.     bind_to_key("^\\",command_completion);    /* CTRL-\ */ 
  376.     bind_to_key("\035",BOGUS);
  377.     bind_to_key("^^",insert_stop_char);    /* CTRL-^ *//* JJD 9-86 */
  378.     bind_to_key("^_",insert_start_char);    /* CTRL-_ *//* JJD 9-86 */
  379.     for(x=' ';x<'(';x++){
  380.         buf[0]=x;
  381.         bind_to_key(buf,self_insert);
  382.     }
  383.     bind_to_key("(",open_paren);    /* electric-( *//* Elec-( */
  384.     bind_to_key(")",close_paren);    /* electric-) *//* Elec-) */
  385.     for(x='*';x< '\\';x++){
  386.         buf[0]=x;
  387.         bind_to_key(buf,self_insert);
  388.     }
  389.     bind_to_key("\\\\",self_insert); /* need 4 \'s ! */
  390.     bind_to_key("]",self_insert);
  391.     bind_to_key("\\^",self_insert);
  392.     for(x='_';x<= '~';x++){
  393.         buf[0]=x;
  394.         bind_to_key(buf,self_insert);
  395.     }
  396.  
  397.     bind_to_key("\177",insert_interrupt_char);    /* DEL key *//* JJD 2-89 */
  398.     
  399.  
  400.     bind_to_key("^[^[",discard_current_edit_line);    /* ESC-ESC */
  401.     bind_to_key("^[ ",toggle_add_space_mode);    /* ESC-space */
  402.     bind_to_key("^[(",backward_paren);    /* ESC-( */
  403.     bind_to_key("^[)",forward_paren);    /* ESC-) */
  404.     bind_to_key("^[-",ul_to_dash_word);    /* ESC--  */
  405.     bind_to_key("^[=",previous_line);    /* ESC-=  */
  406.     bind_to_key("^[?",describe_bindings);    /* ESC-?  */
  407.     bind_to_key("^[E",toggle_eol_only_mode);    /* ESC-E  *//* JJD 9-86 */
  408.     bind_to_key("^[C",describe_arguments);
  409.     bind_to_key("^[F",toggle_eol_longer_mode);    /* ESC-F  *//* JJD 9-86 */
  410.     bind_to_key("^[L",toggle_lisp_mode);    /* ESC-L  */
  411.     bind_to_key("^[N",toggle_nl_truncate_mode);    /* ESC-N  *//* JJD 9-86 */
  412.     bind_to_key("^[P",toggle_pred_mode);    /* ESC-P  *//* JJD 9-86 */
  413.     bind_to_key("^[Q",insert_quit_char);    /* ESC-Q  *//* JJD 3-89 */
  414.     bind_to_key("^[S",toggle_show_eol_mode);
  415.     bind_to_key("^[_",dash_to_ul_word);    /* ESC-_  */
  416.     bind_to_key("^[b",backward_word);    /* ESC-b  */
  417.     bind_to_key("^[c",capitalize_word);    /* ESC-c  */
  418.     bind_to_key("^[d",delete_word);    /* ESC-d  */
  419.     bind_to_key("^[e",toggle_eol_only_mode);    /* ESC-e  *//* JJD 9-86 */
  420.     bind_to_key("^[f",forward_word);    /* ESC-f  */
  421.     bind_to_key("^[g",prime_from_file);    /* ESC-g  *//* JJD 9-86 */
  422.     bind_to_key("^[h",backspace_word);    /* ESC-h  */
  423.     bind_to_key("^[k",delete_region_to_killbuffer);    /* ESC-k  *//* JJD 3-89 */
  424.     bind_to_key("^[l",lowercase_word);    /* ESC-l  */
  425.     bind_to_key("^[m",run_mesg);    /* ESC-m  */
  426.     bind_to_key("^[o",run_pp);/* ESC-o  *//* JJD 9-86 */
  427.     bind_to_key("^[p",toggle_pred_mode);    /* ESC-p  *//* JJD 9-86 */
  428.     bind_to_key("^[q",show_free_nodes);    /* ESC-q  *//* JJD 1-87 */
  429.     bind_to_key("^[r",run_tty_program);    /* ESC-r  */
  430.     bind_to_key("^[t",BOGUS);
  431.     bind_to_key("^[t",run_talk);    /* ESC-t  */
  432.     bind_to_key("^[u",uppercase_word);    /* ESC-u  */
  433.     bind_to_key("^[v",show_version);    /* ESC-v  *//* JJD 3-89 */
  434.     bind_to_key("^[w",run_write);    /* ESC-w  */
  435.     bind_to_key("^[z",run_ruptime);    /* ESC-z  *//* JJD 2-89 */
  436.  
  437.     bind_termcap_key("ku",previous_line);    /* ESC-[-A */
  438.     bind_termcap_key("kd",next_line);    /* ESC-[-B */
  439.     bind_termcap_key("kl",backward_char);    /* ESC-[-C */
  440.     bind_termcap_key("kr",forward_char);    /* ESC-[-D */
  441. }
  442.  
  443.  
  444. file()
  445. {
  446.     int             status;
  447.  
  448.     fd_set readfd;
  449.     int num;
  450.     char buf[1024];
  451.  
  452.     if(!silent){
  453.         printf("Welcome to the Reactive Keyboard. \r\n");
  454.         printf("Written at the University of Calgary. \r\n");
  455.         printf("Version:%s\r\n",VERSION);
  456.         printf("Please wait until your shell prompt appears (ESC-? for help).\r\n");
  457.     }
  458.     init_reactive();    /* MAY TAKE TIME CREATING FREE LIST,     JJD
  459.                  * 9-86 */
  460.     signal(SIGCHLD, childdied);
  461.     signal(SIGSEGV, cleanup);
  462.     if (pred_mode) make_a_prediction (pred_buff); 
  463.     while(1){
  464.         if (pred_mode && pred_buff[0]) {
  465.             /*
  466.              * if (pred_mode && !(eol_only_mode &&
  467.              * *(editor_data.dot))) JJD 9-86
  468.              */
  469.             ioctl(pty_master, TIOCGETP, &pty_sgtty);
  470.             if ((pty_sgtty.sg_flags & ECHO) &&
  471.                 !(pty_sgtty.sg_flags & (RAW | CBREAK)))
  472.                 display_pred_buffer(&editor_data);
  473.         }
  474.         FD_ZERO(&readfd);
  475.         FD_SET(0,&readfd);
  476.         FD_SET(pty_master,&readfd);
  477.         if(select(getdtablesize(),&readfd,0,0,0)<0){
  478.             if( errno == EINTR ){
  479.                 errno = 0;
  480.                 continue;
  481.             }
  482.             else
  483.                 perror("Select");
  484.         }
  485.         if( FD_ISSET(0,&readfd)){
  486.             ioctl(pty_master, TIOCGETP, &pty_sgtty);
  487.             if ((pty_sgtty.sg_flags & ECHO) &&
  488.               !(pty_sgtty.sg_flags & (RAW | CBREAK))) {
  489.                 num = edit_line(buf);
  490.             } else
  491.             num = READ(0, buf, 1024);
  492.             write(pty_master, buf, num);
  493.         }
  494.         if( FD_ISSET(pty_master,&readfd)){
  495.             if (pred_on_display)
  496.                 erase_pred_buffer(&editor_data);    /* JJD9-86 */
  497.             erase_current_edit_line (&editor_data);
  498.             /* JJD: no FILE, keep bigger read size */
  499.             num = READ(pty_master, buf, 1024);
  500.             write(1, buf, num);
  501.         }    
  502.     }
  503. }
  504.  
  505.  
  506. shutdown_pty_and_tty()
  507. {
  508.     close(pty_master);
  509.     ioctl(0, TIOCSETP, &old_stdin);
  510. }
  511.  
  512.  
  513. int 
  514. edit_line(c)
  515.     char           *c;
  516. {
  517.  
  518.     char            ch;
  519.     int             status, num;
  520.     fd_set readfd;
  521.     char            tstring[1024], *cptr;
  522.     int             count;
  523.     struct stat     buf;    /* JJD 3-89 was 512 */
  524.  
  525.     struct ed_buffs *buf_to_use, *cur_line;
  526.     FILE           *from, *popen();
  527.  
  528.     status = OK;
  529.  
  530.     buf_to_use = editor_data.current_ed_buff_ptr;
  531.     while ((status == OK) || (status == HAVE_CHAR)) {
  532.         FD_ZERO(&readfd);
  533.         FD_SET(0,&readfd);
  534.         FD_SET(pty_master,&readfd);
  535.         if(select(getdtablesize(),&readfd,0,0,0)<0){
  536.             if( errno == EINTR ){
  537.                 errno = 0;
  538.                 continue;
  539.             }
  540.             else
  541.                 perror("Select");
  542.         }
  543.         if( FD_ISSET(0,&readfd)){
  544.             READ(0, &ch, 1);
  545.             ch &= 127;    /* Must do this due to parity bit
  546.                      * over dial-up lines */
  547.             /* Possibly needed for other lines too.          */
  548.             editor_data.current_input_char = ch;
  549.             if (pred_on_display)
  550.                     erase_pred_buffer(&editor_data);
  551.                 status = keymap[(int) ch][0] (&editor_data);
  552.             if (pred_mode && ((status == OK) || (status == HAVE_CHAR))) {
  553.                 make_a_prediction(pred_buff);
  554.                 if (pred_buff[0])
  555.                     display_pred_buffer(&editor_data);
  556.             }
  557.         }else{
  558.             num = READ(pty_master, temp_str, 32);
  559.             if(num){
  560.                 erase_current_edit_line(&editor_data);
  561.                 write(1, temp_str, num);
  562.                 draw_current_edit_line (&editor_data);
  563.                 if (pred_buff[0]&&pred_mode)
  564.                     display_pred_buffer(&editor_data);
  565.             }
  566.  
  567.         }
  568.         /* MOVED if (pred_mode... up into if (readfds... above */
  569.     }
  570.  
  571.     switch (status) {
  572.     case FINISHED_EDITING:
  573.         strcpy(c, editor_data.current_buffer);
  574.         if ((strlen(c) != 0)) {
  575.             if (stat(c, &buf) != -1) {    /* if just a directory
  576.                              * name on command line,
  577.                              * assume cd  */
  578.  
  579.                 /*
  580.                  * JJD: this is kind of dicey as is, assumes
  581.                  * a bit too much about dir names
  582.                  */
  583.                 /*
  584.                  * it should check that it is the only thing
  585.                  * on the line for one thing
  586.                  */
  587.  
  588.                 if ((buf.st_mode & S_IFMT) == S_IFDIR) {
  589.                     if (strcmp(".", c) != 0) {    /* JJD 3-89 del . case
  590.                                      * for ed... */
  591.                         strcpy(tstring, "cd ");
  592.                         strcat(tstring, c);
  593.                         strcpy(c, tstring);
  594.                     }
  595.                 }
  596.             }
  597.         }
  598.         /*
  599.          * JJD: to be really useful, this should also know about
  600.          * pushd and popd
  601.          */
  602.  
  603.         if ((strncmp(c, "cd ", 3) == 0) ||
  604.             (strncmp(c, "chdir ", 6) == 0) ||
  605.             (strcmp(c, "cd") == 0) ||
  606.             (strcmp(c, "chdir") == 0)) {
  607.             if (strncmp(c, "cd ", 3) == 0)
  608.                 cptr = &c[2];    /* JJD 3-89, c[-1]  */
  609.             else
  610.                 cptr = &c[5];
  611.             while ((*cptr == ' ') || (*cptr == '\t'))
  612.                 cptr++;
  613.             if ((*cptr == '\0') ||
  614.                 (strcmp(c, "chdir") == 0) ||
  615.                 (strcmp(c, "cd") == 0))
  616.                 strcpy(tstring, getenv("HOME"));
  617.             else {
  618.                 tstring[0] = '\0';
  619.                 if (*cptr == '~') {    /* JJD 3-89 added
  620.                              * abspath, rewrote */
  621.                     char           *optr = cptr;
  622.                     if (*(++cptr)) {
  623.                         while ((*cptr != '\0') && (*cptr != ';'))
  624.                             cptr++;
  625.                         *cptr = '\0';
  626.                         if(myabspath(optr, tstring))
  627.                             strcpy(tstring,".");
  628.                             /* we have an error so stay in the current dir */
  629.                     } else {
  630.                         strcpy(tstring, getenv("HOME"));
  631.                     }    /* ... to here */
  632.                     count = strlen(tstring);
  633.                 } else 
  634.                     count = 0;
  635.                 for (; (*cptr != '\0') && (*cptr != ';'); cptr++, count++)
  636.                     tstring[count] = *cptr;
  637.                 tstring[count] = '\0';
  638.     
  639.             }
  640.             chdir(tstring);
  641.         }
  642.         strcat(c, "\n");/* JJD 2-89 changed ^M to \n */
  643.         cur_line = editor_data.current_ed_buff_ptr;
  644.         cur_line->dot = editor_data.dot;
  645.         cur_line->mark = editor_data.mark;
  646.         if (cur_line != buf_to_use) {
  647.             strcpy(buf_to_use->string, cur_line->string);
  648.             buf_to_use->dot =
  649.                 &buf_to_use->string[cur_line->dot - cur_line->string];
  650.             buf_to_use->mark =
  651.                 &buf_to_use->string[cur_line->mark - cur_line->string];
  652.  
  653.         }
  654.         if (*(buf_to_use->string)) {
  655.             editor_data.current_ed_buff_ptr = buf_to_use->next_ptr;
  656.             editor_data.current_ed_buff_ptr->dot =
  657.                 editor_data.current_ed_buff_ptr->string;
  658.             editor_data.dot = editor_data.current_ed_buff_ptr->dot;
  659.             /*
  660.              * editor_data.current_ed_buff_ptr->mark =
  661.              * editor_data.current_ed_buff_ptr->string;
  662.              */
  663.             editor_data.mark = editor_data.current_ed_buff_ptr->mark;
  664.             *editor_data.dot = '\0';
  665.             editor_data.current_buffer = editor_data.dot;
  666.         } else {
  667.             editor_data.current_ed_buff_ptr = buf_to_use;
  668.             editor_data.current_buffer = buf_to_use->string;
  669.             editor_data.dot = buf_to_use->dot;
  670.             editor_data.mark = buf_to_use->mark;
  671.         }
  672.  
  673.         strcat(c, "");
  674.         update_the_model(c);    /* JJD 9-86 */
  675.         if (pred_mode)
  676.             make_a_prediction(pred_buff);    /* JJD 9-86 */
  677.         return strlen(c);
  678.         break;
  679.  
  680.     case FINISHED_BUT_DONT_ADD_CTRL_M:
  681.         strcpy(c, editor_data.current_buffer);
  682.         editor_data.dot = editor_data.current_buffer;
  683.         editor_data.mark = editor_data.current_buffer;
  684.         *editor_data.dot = '\0';
  685.         return (strlen(c));
  686.         break;
  687.     }
  688.     strcpy(c, "");
  689.     return 0;
  690. }
  691.  
  692.  
  693. int 
  694. get_display_length(s)
  695.     char           *s;
  696. {
  697.  
  698.     char           *cptr;
  699.     int             len;
  700.  
  701.     cptr = s;
  702.     len = 0;
  703.     while (*cptr) {
  704.         if ((*cptr < 32) || (*cptr == 127))
  705.             len += 2;
  706.         else
  707.             len++;
  708.         ++cptr;
  709.     }
  710.     return len;
  711. }
  712.  
  713. int 
  714. get_char_display_length(c)
  715.     char            c;
  716. {
  717.  
  718.     int             len;
  719.  
  720.     len = 0;
  721.     if ((c < 32) || (c == 127))
  722.         len = 2;
  723.     else
  724.         len++;
  725.     return len;
  726. }
  727.  
  728. int 
  729. display_string_into_output_string(s)
  730.     char           *s;
  731. {
  732.  
  733.     int             len;
  734.     char           *cptr;
  735.  
  736.     cptr = s;
  737.     len = 0;
  738.     while (*cptr) {
  739.         if (*cptr < 32) {
  740.             len += 2;
  741.             output_string[output_string_length++] = '^';
  742.             output_string[output_string_length++] =
  743.                 *cptr++ + '@';
  744.         } else if (*cptr == 127) {
  745.             len += 2;
  746.             output_string[output_string_length++] = '^';
  747.             output_string[output_string_length++] = '?';
  748.             ++cptr;
  749.         } else {
  750.             len++;
  751.             output_string[output_string_length++] = *cptr++;
  752.         }
  753.     }
  754.  
  755.     return len;
  756. }
  757.  
  758. int 
  759. display_char_into_output_string(c)
  760.     char            c;
  761. {
  762.  
  763.     int             len;
  764.  
  765.     len = 0;
  766.     if (c < 32) {
  767.         len += 2;
  768.         output_string[output_string_length++] = '^';
  769.         output_string[output_string_length++] = c + '@';
  770.     } else if (c == 127) {
  771.         len += 2;
  772.         output_string[output_string_length++] = '^';
  773.         output_string[output_string_length++] = '?';
  774.     } else {
  775.         len++;
  776.         output_string[output_string_length++] = c;
  777.     }
  778.  
  779.     return len;
  780. }
  781.  
  782. int 
  783. erase_current_edit_line(e)
  784.     ED_STRUCT      *e;
  785. {
  786.  
  787.     int             num_to_erase, count;
  788.     char           *old_dot;
  789.  
  790.     /*
  791.      * added to deal with META-prefixes which turn pred display on...may
  792.      * not work for all cases
  793.      */
  794.     if (pred_on_display)
  795.         erase_pred_buffer(e);    /* JJD 9-86 */
  796.     old_dot = e->dot;
  797.     beginning_of_line(e);
  798.     e->dot = old_dot;
  799.     output_string_length = 0;
  800.  
  801.     num_to_erase = get_display_length(e->current_buffer);
  802.     for (count = num_to_erase; count; --count)
  803.         output_string[output_string_length++] = ' ';
  804.     for (count = num_to_erase; count; --count)
  805.         tputs(cursor_left, ONE_LINE, append_to_output_string);
  806.     write(1, output_string, output_string_length);
  807.  
  808.     return OK;
  809. }
  810.  
  811. int 
  812. draw_current_edit_line(e)
  813.     ED_STRUCT      *e;
  814. {
  815.  
  816.     int             count;
  817.  
  818.     output_string_length = 0;
  819.     display_string_into_output_string(e->current_buffer);
  820.     count = get_display_length(e->dot);
  821.     for (; count; --count)
  822.         tputs(cursor_left, ONE_LINE, append_to_output_string);
  823.     write(1, output_string, output_string_length);
  824.  
  825.     return OK;
  826. }
  827.