source: git/Singular/feread.cc @ f291109

spielwiese
Last change on this file since f291109 was f291109, checked in by Wilfred Pohl <pohl@…>, 26 years ago
history.h not for WINNT git-svn-id: file:///usr/local/Singular/svn/trunk@1968 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 16.0 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/* $Id: feread.cc,v 1.12 1998-05-25 08:50:23 pohl 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 = myfopen( "/dev/tty", "w" );
229      #else
230        fe_echo = myfopen( 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          fputc(' ',fe_echo);
398          fputc('\b',fe_echo);
399          fflush(fe_echo);
400          change=1;
401        }
402        case feCTRL('D'):  /*delete the character under the cursor or eof*/
403        {
404          int j;
405          if ((i==0)&&(c==feCTRL('D')&&(s[0]=='\0'))) return NULL; /*eof*/
406          if (s[i]!='\0')
407          {
408            j=i;
409            while(s[j]!='\0')
410            {
411              s[j]=s[j+1];
412              fputc(s[j],fe_echo);
413              j++;
414            }
415            fputc(' ',fe_echo);
416            while(j>i)
417            {
418              fputc('\b',fe_echo);
419              j--;
420            }
421          }
422          #ifdef MSDOS
423            fputc('\b',fe_echo);
424          #endif
425          change=1;
426          break;
427        }
428        case feCTRL('A'):  /* move the cursor to the beginning of the line */
429        {
430          while(i>0)
431          {
432            i--;
433            fputc('\b',fe_echo);
434          }
435          break;
436        }
437        case feCTRL('E'): /* move the cursor to the end of the line */
438        {
439          while(s[i]!='\0')
440          {
441            fputc(s[i],fe_echo);
442            i++;
443          }
444          break;
445        }
446        case feCTRL('B'): /* move the cursor backward one character */
447        {
448          i--;
449          fputc('\b',fe_echo);
450          break;
451        }
452        case feCTRL('F'): /* move the cursor forward  one character */
453        {
454          if(s[i]!='\0')
455          {
456            fputc(s[i],fe_echo);
457            i++;
458          }
459          break;
460        }
461        /* change to ^U, to be consistent with readline:*/
462        case feCTRL('U'): /* delete entire input line */
463        {
464          fe_ctrl_x(s,i);
465          memset(s,0,size);
466          change=1;
467          break;
468        }
469        case feCTRL('W'): /* test hist. */
470        {
471          int i;
472          PrintS("\nstart hist\n");
473          for(i=0;i<fe_hist_max;i++)
474          {
475            if(fe_hist[i]!=NULL)
476            {
477              Print("%2d ",i);
478              if(i==fe_hist_pos) PrintS("-"); else PrintS(" ");
479              if(i==h) PrintS(">"); else PrintS(" ");
480              PrintS(fe_hist[i]);
481              PrintLn();
482            }
483          }
484          Print("end hist, next_pos=%d\n",fe_hist_pos);
485          break;
486        }
487        case feCTRL('K'): /* delete up to the end of the line */
488        {
489          fe_ctrl_k(s,i);
490          s[i]='\0';
491          change=1;
492          break;
493        }
494        case feCTRL('P'): /* previous line */
495        {
496          fe_ctrl_x(s,i);
497          fe_get_hist(s,size,h,change,-1);
498          while(s[i]!='\0')
499          {
500            fputc(s[i],fe_echo);
501            i++;
502          }
503          change=0;
504          break;
505        }
506        case feCTRL('N'): /* next line */
507        {
508          fe_ctrl_x(s,i);
509          fe_get_hist(s,size,h,change,1);
510          while(s[i]!='\0')
511          {
512            fputc(s[i],fe_echo);
513            i++;
514          }
515          change=0;
516          break;
517        }
518        default:
519        {
520          if ((c>=' ')&&(c<=126))
521          {
522            fputc (c,fe_echo);
523            if (s[i]!='\0')
524            {
525              /* shift by 1 to the right */
526              int j=i;
527              int l;
528              while ((s[j]!='\0')&&(j<size-2)) j++;
529              l=j-i;
530              while (j>i) { s[j]=s[j-1]; j--; }
531              /* display */
532              fwrite(s+i+1,l,1,fe_echo);
533              /* set cursor */
534              while(l>0)
535              {
536                l--;
537                fputc('\b',fe_echo);
538              }
539            }
540            if (i<size-1) s[i]=c;
541            i++;
542            change=1;
543          }
544        }
545      } /* switch */
546      fflush(fe_echo);
547    } /* loop */
548  }
549  /*else*/
550    return fgets(s,size,stdin);
551}
552
553//int main (void)
554//{
555//  char b[200];
556//  char * m_eof;
557//
558//  fe_set_input_mode();
559//  while(1)
560//  {
561//    m_eof=fe_fgets_stdin(b,200);
562//    if (!m_eof) break;
563//    printf(">>%s<<\n",b);
564//  }
565//
566//  return 0;
567//}
568#endif
569/*=======================================================================*/
570#if defined(HAVE_READLINE) && !defined(HAVE_FEREAD)
571
572#include <unistd.h>
573#include <stdio.h>
574#include <stdlib.h>
575#include <sys/types.h>
576#include <sys/file.h>
577#include <sys/stat.h>
578#include <sys/errno.h>
579
580extern "C" {
581#include <readline/readline.h>
582#ifndef WINNT
583#include <readline/history.h>
584#endif
585}
586
587#ifndef STDOUT_FILENO
588#define STDOUT_FILENO 1
589#endif
590
591#include "febase.h"
592#include "ipshell.h"
593
594BOOLEAN fe_use_fgets=FALSE;
595
596/* Tell the GNU Readline library how to complete.  We want to try to complete
597   on command names  or on filenames if it is preceded by " */
598
599/* Generator function for command completion.  STATE lets us know whether
600*   to start from scratch; without any state (i.e. STATE == 0), then we
601*   start at the top of the list.
602*/
603char *command_generator (char *text, int state)
604{
605  static int list_index, len;
606  char *name;
607
608  /* If this is a new word to complete, initialize now.  This includes
609     saving the length of TEXT for efficiency, and initializing the index
610     variable to 0. */
611  if (state==0)
612  {
613    list_index = 1;
614    len = strlen (text);
615  }
616
617  /* Return the next name which partially matches from the command list. */
618  while ((name = cmds[list_index].name)!=NULL)
619  {
620    list_index++;
621
622    if (strncmp (name, text, len) == 0)
623      return (strdup(name));
624  }
625
626  /* If no names matched, then return NULL. */
627  return ((char *)NULL);
628}
629
630/* Attempt to complete on the contents of TEXT.  START and END show the
631*   region of TEXT that contains the word to complete.  We can use the
632*   entire line in case we want to do some simple parsing.  Return the
633*   array of matches, or NULL if there aren't any.
634*/
635char ** singular_completion (char *text, int start, int end)
636{
637  /* If this word is not in a string, then it may be a command
638     to complete.  Otherwise it may be the name of a file in the current
639     directory. */
640  if (rl_line_buffer[start-1]=='"')
641    return completion_matches (text, filename_completion_function);
642  char **m=completion_matches (text, command_generator);
643  if (m==NULL)
644  {
645    m=(char **)malloc(2*sizeof(char*));
646    m[0]=(char *)malloc(end-start+2);
647    strncpy(m[0],text,end-start+1);
648    m[1]=NULL;
649  }
650  return m;
651}
652
653void fe_set_input_mode(void)
654{
655  /* Allow conditional parsing of the ~/.inputrc file. */
656  rl_readline_name = "Singular";
657
658  if(!fe_use_fgets)
659  {
660    /* Tell the completer that we want a crack first. */
661    rl_attempted_completion_function = (CPPFunction *)singular_completion;
662
663    /* set the output stream */
664    if(!isatty(STDOUT_FILENO))
665    {
666      #ifdef atarist
667        rl_outstream = myfopen( "/dev/tty", "w" );
668      #else
669        rl_outstream = myfopen( ttyname(fileno(stdin)), "w" );
670      #endif
671    }
672
673    /* try to read a history */
674    using_history();
675    read_history (".singular_hist");
676  } 
677}
678
679void fe_reset_input_mode (void)
680{
681  /* try to read a history */
682  if(!feBatch && !fe_use_fgets && (history_total_bytes()!=0))
683    write_history (".singular_hist");
684}
685
686char * fe_fgets_stdin_rl(char *pr,char *s, int size)
687{
688  if (feBatch)
689    return NULL;
690  if(fe_use_fgets)
691  {
692    PrintS(pr);mflush();
693    return fgets(s,size,stdin);
694  }
695
696  char *line;
697
698  line = readline (pr);
699
700  if (line==NULL)
701    return NULL;
702
703  if (*line!='\0')
704  {
705    add_history (line);
706  }
707  int l=strlen(line);
708  if (l>=size-1)
709  {
710    strncpy(s,line,size);
711  }
712  else
713  {
714    strncpy(s,line,l);
715    s[l]='\n';
716    s[l+1]='\0';
717  }
718  free (line);
719
720  return s;
721}
722#endif
Note: See TracBrowser for help on using the repository browser.