source: git/Singular/feread.cc @ 18dd47

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