source: git/Singular/feread.cc @ 0e1846

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