source: git/Singular/feread.cc @ 1e3015

spielwiese
Last change on this file since 1e3015 was 1e3015, checked in by Hans Schönemann <hannes@…>, 26 years ago
* hanes: TCL-changes (febase.cc feread.cc iplib.cc misc.cc) git-svn-id: file:///usr/local/Singular/svn/trunk@2424 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 17.1 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/* $Id: feread.cc,v 1.18 1998-08-03 16:39:05 Singular Exp $ */
5/*
6* ABSTRACT: input from ttys, simulating fgets
7*/
8
9
10#include "mod2.h"
11#include "tok.h"
12#include "febase.h"
13#include "mmemory.h"
14#ifdef HAVE_TCL
15#include "ipid.h"
16#endif
17
18#ifdef HAVE_FEREAD
19 #include <unistd.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #ifdef MSDOS
24  #include <pc.h>
25 #else
26  #ifdef atarist
27   #include <ioctl.h>
28  #else
29   #ifdef NeXT
30    #include <sgtty.h>
31    #include <sys/ioctl.h>
32   #else
33    #include <termios.h>
34   #endif
35  #endif
36 #endif
37
38
39#ifndef STDIN_FILENO
40#define STDIN_FILENO 0
41#endif
42#ifndef STDOUT_FILENO
43#define STDOUT_FILENO 1
44#endif
45
46#define feCTRL(C) ((C) & 0x1F)    /* <ctrl> character  */
47
48#ifndef MSDOS
49/* Use this variable to remember original terminal attributes. */
50#if defined( atarist ) || defined( NeXT )
51struct sgttyb  fe_saved_attributes;
52#else
53struct termios fe_saved_attributes;
54#endif
55#endif
56
57static BOOLEAN fe_stdout_is_tty;
58static BOOLEAN fe_stdin_is_tty;
59BOOLEAN fe_use_fgets=FALSE;
60static FILE *  fe_echo; /*the output file for echoed characters*/
61
62#define fe_hist_max 32
63char ** fe_hist=NULL;
64int     fe_hist_pos;
65
66#ifndef MSDOS
67  #ifdef HAVE_ATEXIT
68    void fe_reset_input_mode (void)
69  #else
70    extern "C" int on_exit(void (*f)(int, void *), void *arg);
71
72    void fe_reset_input_mode (int i, void *v)
73  #endif
74  {
75    if (fe_stdin_is_tty)
76    {
77      #ifdef atarist
78        stty(0, &fe_saved_attributes);
79      #else
80        #ifdef NeXT
81          ioctl(STDIN_FILENO, TIOCSETP, &fe_saved_attributes);
82        #else
83          tcsetattr (STDIN_FILENO, TCSANOW, &fe_saved_attributes);
84        #endif
85      #endif
86      fe_stdin_is_tty=0;
87      int i;
88      for(i=fe_hist_max-1;i>=0;i--)
89      {
90        FreeL((ADDRESS)fe_hist[i]);
91      }
92      Free((ADDRESS)fe_hist,fe_hist_max*sizeof(char *));
93      fe_hist=NULL;
94      if (!fe_stdout_is_tty)
95      {
96        fclose(fe_echo);
97      }
98    }
99  }
100  void fe_temp_reset (void)
101  {
102    if (fe_stdin_is_tty)
103    {
104      #ifdef atarist
105        stty(0, &fe_saved_attributes);
106      #else
107        #ifdef NeXT
108          ioctl(STDIN_FILENO, TIOCSETP, &fe_saved_attributes);
109        #else
110          tcsetattr (STDIN_FILENO, TCSANOW, &fe_saved_attributes);
111        #endif
112      #endif
113    }
114  }
115  void fe_temp_set (void)
116  {
117    if(fe_stdin_is_tty)
118    {
119      #ifdef atarist
120        /*set line wrap mode*/
121        if(isatty(STDOUT_FILENO))
122        {
123          printf("\033v");
124        }
125      #endif
126      #if defined( atarist ) || defined( NeXT )
127        struct sgttyb tattr;
128      #else
129        struct termios tattr;
130      #endif
131
132      /* Set the funny terminal modes. */
133      #ifdef atarist
134         gtty(0, &tattr);
135         tattr.sg_flags |= RAW;
136         tattr.sg_flags |= CBREAK;
137         tattr.sg_flags &= ~ECHO;
138         stty(0, &tattr);
139      #else
140        #ifdef NeXT
141          ioctl(STDIN_FILENO, TIOCGETP, &tattr);
142          //tattr.sg_flags |= RAW;
143          tattr.sg_flags |= CBREAK;
144          tattr.sg_flags &= ~ECHO;
145          ioctl(STDIN_FILENO, TIOCSETP, &tattr);
146          ioctl(STDOUT_FILENO, TIOCGETP, &tattr);
147          tattr.sg_flags |= CRMOD;
148          ioctl(STDOUT_FILENO, TIOCSETP, &tattr);
149        #else
150          tcgetattr (STDIN_FILENO, &tattr);
151          tattr.c_lflag &= ~(ICANON|ECHO); /* Clear ICANON and ECHO. */
152          tattr.c_cc[VMIN] = 1;
153          tattr.c_cc[VTIME] = 0;
154          tcsetattr (STDIN_FILENO, TCSAFLUSH, &tattr);
155        #endif
156      #endif
157    }
158  }
159#endif
160
161void fe_set_input_mode (void)
162{
163  #ifdef atarist
164    /*set line wrap mode*/
165    if(isatty(STDOUT_FILENO))
166    {
167      printf("\033v");
168    }
169  #endif
170  /* Make sure stdin is a terminal. */
171  if ((!fe_use_fgets) && (isatty (STDIN_FILENO)))
172  {
173    #ifndef MSDOS
174      #if defined( atarist ) || defined( NeXT )
175        struct sgttyb tattr;
176        #ifdef atarist
177          gtty(0, &fe_saved_attributes);
178        #else
179          ioctl(STDIN_FILENO, TIOCGETP, &fe_saved_attributes);
180        #endif
181      #else
182        struct termios tattr;
183
184        /* Save the terminal attributes so we can restore them later. */
185        tcgetattr (STDIN_FILENO, &fe_saved_attributes);
186      #endif
187      #ifdef HAVE_ATEXIT
188        atexit(fe_reset_input_mode);
189      #else
190        on_exit(fe_reset_input_mode,NULL);
191      #endif
192
193      /* Set the funny terminal modes. */
194      #ifdef atarist
195        gtty(0, &tattr);
196        tattr.sg_flags |= RAW;
197        tattr.sg_flags |= CBREAK;
198        tattr.sg_flags &= ~ECHO;
199        stty(0, &tattr);
200      #else
201        #ifdef NeXT
202          ioctl(STDIN_FILENO, TIOCGETP, &tattr);
203          //tattr.sg_flags |= RAW;
204          tattr.sg_flags |= CBREAK;
205          tattr.sg_flags &= ~ECHO;
206          ioctl(STDIN_FILENO, TIOCSETP, &tattr);
207          ioctl(STDOUT_FILENO, TIOCGETP, &tattr);
208          tattr.sg_flags |= CRMOD;
209          ioctl(STDOUT_FILENO, TIOCSETP, &tattr);
210        #else
211          tcgetattr (STDIN_FILENO, &tattr);
212          tattr.c_lflag &= ~(ICANON|ECHO); /* Clear ICANON and ECHO. */
213          tattr.c_cc[VMIN] = 1;
214          tattr.c_cc[VTIME] = 0;
215          tcsetattr (STDIN_FILENO, TCSAFLUSH, &tattr);
216        #endif
217      #endif
218    #endif
219
220    fe_stdin_is_tty=1;
221
222    /*setup echo*/
223    if(isatty(STDOUT_FILENO))
224    {
225      fe_stdout_is_tty=1;
226      fe_echo=stdout;
227    }
228    else
229    {
230      fe_stdout_is_tty=0;
231      #ifdef atarist
232        fe_echo = myfopen( "/dev/tty", "w" );
233      #else
234        fe_echo = myfopen( ttyname(fileno(stdin)), "w" );
235      #endif
236    }
237
238    /* setup history */
239    fe_hist=(char **)Alloc0(fe_hist_max*sizeof(char *));
240    fe_hist_pos=0;
241  }
242  else
243  {
244    fe_stdin_is_tty=0;
245    fe_echo=stdout;
246  }
247}
248
249static void fe_ctrl_k(char *s,int i)
250{
251  int j=i;
252  while(s[j]!='\0')
253  {
254    fputc(' ',fe_echo);
255    j++;
256  }
257  while(j>i)
258  {
259    fputc('\b',fe_echo);
260    j--;
261  }
262}
263
264static void fe_ctrl_x(char *s,int &i)
265{
266  fe_ctrl_k(s,i);
267  while(i>0)
268  {
269    i--;
270    fputc('\b',fe_echo);
271    fputc(' ',fe_echo);
272    fputc('\b',fe_echo);
273  }
274}
275
276/*2
277* add s to the history
278* if s is no the previous one, duplicate it
279*/
280static void fe_add_hist(char *s)
281{
282  if (s[0]!='\0') /* skip empty lines */
283  {
284    /* compare this line*/
285    if (fe_hist_pos!=0)
286    {
287      if ((fe_hist[fe_hist_pos-1]!=NULL)
288      && (strcmp(fe_hist[fe_hist_pos-1],s)==0))
289        return;
290    }
291    else
292    {
293      if ((fe_hist[fe_hist_max-1]!=NULL)
294      && (strcmp(fe_hist[fe_hist_max-1],s)==0))
295        return;
296    }
297    /* normal case: enter a new line */
298    /* first free the slot at position fe_hist_pos */
299    if (fe_hist[fe_hist_pos]!=NULL)
300    {
301      FreeL((ADDRESS)fe_hist[fe_hist_pos]);
302    }
303    /* and store a duplicate */
304    fe_hist[fe_hist_pos]=mstrdup(s);
305    /* increment fe_hist_pos in a circular manner */
306    fe_hist_pos++;
307    if (fe_hist_pos==fe_hist_max) fe_hist_pos=0;
308  }
309}
310
311static void fe_get_hist(char *s, int size, int &pos,int change, int incr)
312{
313  if (change)
314    fe_add_hist(s);
315  do
316  {
317    pos+=incr;
318    if(pos>=fe_hist_max) pos-=fe_hist_max;
319    else if(pos<0)       pos+=fe_hist_max;
320  }
321  while ((pos!=0)&&(fe_hist[pos]==NULL));
322  memset(s,0,size);
323  if (fe_hist[pos]!=NULL)
324  {
325    strncpy(s,fe_hist[pos],size-2);
326  }
327}
328
329char * fe_fgets_stdin(char *s, int size)
330{
331  #ifdef HAVE_TCL
332  if (tclmode)
333  {
334    if(currRing!=NULL) PrintTCLS('P',pr);
335    else               PrintTCLS('U',pr);
336  }
337  else
338  #endif
339  if ((BVERBOSE(V_PROMPT))&&(!feBatch))
340  {
341    PrintS(pr);
342  }
343  mflush();
344
345  if (fe_stdin_is_tty)
346  {
347    int h=fe_hist_pos;
348    int change=0;
349    #ifdef MSDOS
350      int c;
351    #else
352      char c;
353    #endif
354    int i=0;
355    memset(s,0,size);
356
357    loop
358    {
359      #ifndef MSDOS
360        c=0;
361        read (STDIN_FILENO, &c, 1);
362      #else
363        c=getkey();
364      #endif
365      #ifndef MSDOS
366      if (c == 033)
367      {
368        /* check for CSI */
369        c=0;
370        read (STDIN_FILENO, &c, 1);
371        if (c == '[')
372        {
373          /* get command character */
374          c=0;
375          read (STDIN_FILENO, &c, 1);
376          switch (c)
377          {
378            case 'D': /* left arrow key */
379              c = feCTRL('B')/*002*/;
380              break;
381            case 'C': /* right arrow key */
382              c = feCTRL('F')/*006*/;
383              break;
384            case 'A': /* up arrow key */
385              c = feCTRL('P')/*020*/;
386              break;
387            case 'B': /* down arrow key */
388              c = feCTRL('N')/*016*/;
389              break;
390          }
391        }
392      }
393      #endif
394      switch(c)
395      {
396        case feCTRL('M'):
397        case feCTRL('J'):
398        {
399          fe_add_hist(s);
400          i=strlen(s);
401          if (i<size-1) s[i]='\n';
402          fputc('\n',fe_echo);
403          fflush(fe_echo);
404          return s;
405        }
406        #ifdef MSDOS
407          case 0x153:
408        #endif
409        case feCTRL('H'):
410        case 127:       /*delete the character left of the cursor*/
411        {
412          if (i==0) break;
413          i--;
414          fputc('\b',fe_echo);
415          fputc(' ',fe_echo);
416          fputc('\b',fe_echo);
417          fflush(fe_echo);
418          change=1;
419        }
420        case feCTRL('D'):  /*delete the character under the cursor or eof*/
421        {
422          int j;
423          if ((i==0)&&(c==feCTRL('D')&&(s[0]=='\0'))) return NULL; /*eof*/
424          if (s[i]!='\0')
425          {
426            j=i;
427            while(s[j]!='\0')
428            {
429              s[j]=s[j+1];
430              fputc(s[j],fe_echo);
431              j++;
432            }
433            fputc(' ',fe_echo);
434            while(j>i)
435            {
436              fputc('\b',fe_echo);
437              j--;
438            }
439          }
440          #ifdef MSDOS
441            fputc('\b',fe_echo);
442          #endif
443          change=1;
444          break;
445        }
446        case feCTRL('A'):  /* move the cursor to the beginning of the line */
447        {
448          while(i>0)
449          {
450            i--;
451            fputc('\b',fe_echo);
452          }
453          break;
454        }
455        case feCTRL('E'): /* move the cursor to the end of the line */
456        {
457          while(s[i]!='\0')
458          {
459            fputc(s[i],fe_echo);
460            i++;
461          }
462          break;
463        }
464        case feCTRL('B'): /* move the cursor backward one character */
465        {
466          i--;
467          fputc('\b',fe_echo);
468          break;
469        }
470        case feCTRL('F'): /* move the cursor forward  one character */
471        {
472          if(s[i]!='\0')
473          {
474            fputc(s[i],fe_echo);
475            i++;
476          }
477          break;
478        }
479        /* change to ^U, to be consistent with readline:*/
480        case feCTRL('U'): /* delete entire input line */
481        {
482          fe_ctrl_x(s,i);
483          memset(s,0,size);
484          change=1;
485          break;
486        }
487        case feCTRL('W'): /* test hist. */
488        {
489          int i;
490          PrintS("\nstart hist\n");
491          for(i=0;i<fe_hist_max;i++)
492          {
493            if(fe_hist[i]!=NULL)
494            {
495              Print("%2d ",i);
496              if(i==fe_hist_pos) PrintS("-"); else PrintS(" ");
497              if(i==h) PrintS(">"); else PrintS(" ");
498              PrintS(fe_hist[i]);
499              PrintLn();
500            }
501          }
502          Print("end hist, next_pos=%d\n",fe_hist_pos);
503          break;
504        }
505        case feCTRL('K'): /* delete up to the end of the line */
506        {
507          fe_ctrl_k(s,i);
508          s[i]='\0';
509          change=1;
510          break;
511        }
512        case feCTRL('P'): /* previous line */
513        {
514          fe_ctrl_x(s,i);
515          fe_get_hist(s,size,h,change,-1);
516          while(s[i]!='\0')
517          {
518            fputc(s[i],fe_echo);
519            i++;
520          }
521          change=0;
522          break;
523        }
524        case feCTRL('N'): /* next line */
525        {
526          fe_ctrl_x(s,i);
527          fe_get_hist(s,size,h,change,1);
528          while(s[i]!='\0')
529          {
530            fputc(s[i],fe_echo);
531            i++;
532          }
533          change=0;
534          break;
535        }
536        default:
537        {
538          if ((c>=' ')&&(c<=126))
539          {
540            fputc (c,fe_echo);
541            if (s[i]!='\0')
542            {
543              /* shift by 1 to the right */
544              int j=i;
545              int l;
546              while ((s[j]!='\0')&&(j<size-2)) j++;
547              l=j-i;
548              while (j>i) { s[j]=s[j-1]; j--; }
549              /* display */
550              fwrite(s+i+1,l,1,fe_echo);
551              /* set cursor */
552              while(l>0)
553              {
554                l--;
555                fputc('\b',fe_echo);
556              }
557            }
558            if (i<size-1) s[i]=c;
559            i++;
560            change=1;
561          }
562        }
563      } /* switch */
564      fflush(fe_echo);
565    } /* loop */
566  }
567  /*else*/
568    return fgets(s,size,stdin);
569}
570
571//int main (void)
572//{
573//  char b[200];
574//  char * m_eof;
575//
576//  fe_set_input_mode();
577//  while(1)
578//  {
579//    m_eof=fe_fgets_stdin(b,200);
580//    if (!m_eof) break;
581//    printf(">>%s<<\n",b);
582//  }
583//
584//  return 0;
585//}
586#endif
587/*=======================================================================*/
588#if defined(HAVE_READLINE) && !defined(HAVE_FEREAD)
589
590 #include <unistd.h>
591 #include <stdio.h>
592 #include <stdlib.h>
593 #include <sys/types.h>
594 #include <sys/file.h>
595 #include <sys/stat.h>
596 #include <sys/errno.h>
597
598extern "C" {
599 #ifdef READLINE_READLINE_H_OK
600  #include <readline/readline.h>
601  #ifdef HAVE_READLINE_HISTORY_H
602   #include <readline/history.h>
603  #endif
604 #else /* declare everything we need explicitely and do not rely on includes */
605  extern char * rl_readline_name;
606  extern char *rl_line_buffer;
607  char *filename_completion_function();
608  typedef char **CPPFunction ();
609  extern char ** completion_matches ();
610  extern CPPFunction * rl_attempted_completion_function;
611  extern FILE * rl_outstream;
612  char * readline ();
613  void add_history ();
614  int write_history ();
615 #endif /* READLINE_READLINE_H_OK */
616}
617
618#ifndef STDOUT_FILENO
619#define STDOUT_FILENO 1
620#endif
621
622#include "ipshell.h"
623
624BOOLEAN fe_use_fgets=FALSE;
625
626/* Tell the GNU Readline library how to complete.  We want to try to complete
627   on command names  or on filenames if it is preceded by " */
628
629/* Generator function for command completion.  STATE lets us know whether
630*   to start from scratch; without any state (i.e. STATE == 0), then we
631*   start at the top of the list.
632*/
633char *command_generator (char *text, int state)
634{
635  static int list_index, len;
636  char *name;
637
638  /* If this is a new word to complete, initialize now.  This includes
639     saving the length of TEXT for efficiency, and initializing the index
640     variable to 0. */
641  if (state==0)
642  {
643    list_index = 1;
644    len = strlen (text);
645  }
646
647  /* Return the next name which partially matches from the command list. */
648  while ((name = cmds[list_index].name)!=NULL)
649  {
650    list_index++;
651
652    if (strncmp (name, text, len) == 0)
653      return (strdup(name));
654  }
655
656  /* If no names matched, then return NULL. */
657  return ((char *)NULL);
658}
659
660/* Attempt to complete on the contents of TEXT.  START and END show the
661*   region of TEXT that contains the word to complete.  We can use the
662*   entire line in case we want to do some simple parsing.  Return the
663*   array of matches, or NULL if there aren't any.
664*/
665char ** singular_completion (char *text, int start, int end)
666{
667  /* If this word is not in a string, then it may be a command
668     to complete.  Otherwise it may be the name of a file in the current
669     directory. */
670  if (rl_line_buffer[start-1]=='"')
671    return completion_matches (text, filename_completion_function);
672  char **m=completion_matches (text, command_generator);
673  if (m==NULL)
674  {
675    m=(char **)malloc(2*sizeof(char*));
676    m[0]=(char *)malloc(end-start+2);
677    strncpy(m[0],text,end-start+1);
678    m[1]=NULL;
679  }
680  return m;
681}
682
683void fe_set_input_mode(void)
684{
685  /* Allow conditional parsing of the ~/.inputrc file. */
686  rl_readline_name = "Singular";
687
688  if(!fe_use_fgets)
689  {
690    /* Tell the completer that we want a crack first. */
691    rl_attempted_completion_function = (CPPFunction *)singular_completion;
692
693    /* set the output stream */
694    if(!isatty(STDOUT_FILENO))
695    {
696      #ifdef atarist
697        rl_outstream = myfopen( "/dev/tty", "w" );
698      #else
699        rl_outstream = myfopen( ttyname(fileno(stdin)), "w" );
700      #endif
701    }
702
703    /* try to read a history */
704    using_history();
705    char *p = getenv("SINGULARHIST");
706    if (p != NULL)
707    {
708      read_history (p);
709    }
710  }
711}
712
713void fe_reset_input_mode (void)
714{
715  char *p = getenv("SINGULARHIST");
716  if (p != NULL)
717  {
718    if(!feBatch && !fe_use_fgets && (history_total_bytes()!=0))
719      write_history (p);
720  }
721}
722
723char * fe_fgets_stdin_rl(char *pr,char *s, int size)
724{
725  if (feBatch)
726    return NULL;
727  if(fe_use_fgets)
728  {
729    #ifdef HAVE_TCL
730    if (tclmode)
731    {
732      if(currRing!=NULL) PrintTCLS('P',pr);
733      else               PrintTCLS('U',pr);
734    }
735    else
736    #endif
737    if (BVERBOSE(V_PROMPT))
738    {
739      PrintS(pr);
740    }
741    mflush();
742    return fgets(s,size,stdin);
743  }
744
745  if (!BVERBOSE(V_PROMPT))
746  {
747    pr="";
748  }
749  mflush();
750
751  char *line;
752  line = readline (pr);
753
754  if (line==NULL)
755    return NULL;
756
757  if (*line!='\0')
758  {
759    add_history (line);
760  }
761  int l=strlen(line);
762  if (l>=size-1)
763  {
764    strncpy(s,line,size);
765  }
766  else
767  {
768    strncpy(s,line,l);
769    s[l]='\n';
770    s[l+1]='\0';
771  }
772  free (line);
773
774  return s;
775}
776#endif
Note: See TracBrowser for help on using the repository browser.