source: git/Singular/fereadl.c @ c34e3d

fieker-DuValspielwiese
Last change on this file since c34e3d was c34e3d, checked in by Hans Schönemann <hannes@…>, 24 years ago
* hannes: minor fix git-svn-id: file:///usr/local/Singular/svn/trunk@3963 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: fereadl.c,v 1.6 1999-12-06 18:29:51 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#include "structs.h"
15#include "febase.h"
16
17#ifdef HAVE_FEREAD
18 #include <unistd.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #ifdef MSDOS
23  #include <pc.h>
24 #else
25  #ifdef HAVE_TERM_H
26  #include <term.h>
27  #elif HAVE_TERMCAP_H
28  #include <termcap.h>
29  #elif HAVE_TERMIOS_H
30  #include <termios.h>
31  #endif
32
33  #ifdef atarist
34   #include <ioctl.h>
35  #else
36   #ifdef NeXT
37    #include <sgtty.h>
38    #include <sys/ioctl.h>
39   #endif
40  #endif
41 #endif
42
43
44#ifndef STDIN_FILENO
45#define STDIN_FILENO 0
46#endif
47#ifndef STDOUT_FILENO
48#define STDOUT_FILENO 1
49#endif
50
51#define feCTRL(C) ((C) & 0x1F)    /* <ctrl> character  */
52
53#ifndef MSDOS
54/* Use this variable to remember original terminal attributes. */
55#if defined( atarist ) || defined( NeXT )
56struct sgttyb  fe_saved_attributes;
57#else
58struct termios fe_saved_attributes;
59#endif
60#endif
61
62static BOOLEAN fe_stdout_is_tty;
63static BOOLEAN fe_stdin_is_tty;
64BOOLEAN fe_use_fgets=FALSE;
65static BOOLEAN fe_is_initialized=FALSE;
66FILE *  fe_echo; /*the output file for echoed characters*/
67
68#define fe_hist_max 32
69char ** fe_hist=NULL;
70short   fe_hist_pos;
71short   fe_is_raw_tty=0;
72int     fe_cursor_pos; /* 0..colmax-1*/
73int     fe_cursor_line; /* 0..pagelength-1*/
74
75#ifndef MSDOS
76  #ifndef HAVE_ATEXIT
77    int on_exit(void (*f)(int, void *), void *arg);
78    void fe_reset_fe (int i, void *v)
79  #else
80    void fe_reset_fe (void)
81  #endif
82  {
83    if (fe_stdin_is_tty && fe_is_raw_tty)
84    {
85      int i;
86      #ifdef atarist
87        stty(0, &fe_saved_attributes);
88      #else
89        #ifdef NeXT
90          ioctl(STDIN_FILENO, TIOCSETP, &fe_saved_attributes);
91        #else
92          tcsetattr (STDIN_FILENO, TCSANOW, &fe_saved_attributes);
93        #endif
94      #endif
95      fe_is_raw_tty=0;
96      for(i=fe_hist_max-1;i>=0;i--)
97      {
98        FreeL((ADDRESS)fe_hist[i]);
99      }
100      Free((ADDRESS)fe_hist,fe_hist_max*sizeof(char *));
101      fe_hist=NULL;
102      if (!fe_stdout_is_tty)
103      {
104        fclose(fe_echo);
105      }
106    }
107  }
108  void fe_temp_reset (void)
109  {
110    if (fe_is_raw_tty)
111    {
112      #ifdef atarist
113        stty(0, &fe_saved_attributes);
114      #else
115        #ifdef NeXT
116          ioctl(STDIN_FILENO, TIOCSETP, &fe_saved_attributes);
117        #else
118          tcsetattr (STDIN_FILENO, TCSANOW, &fe_saved_attributes);
119        #endif
120      #endif
121      fe_is_raw_tty=0;
122    }
123  }
124  void fe_temp_set (void)
125  {
126    if(fe_is_raw_tty==0)
127    {
128      #ifdef atarist
129        /*set line wrap mode*/
130        if(fe_stdout_is_tty)
131        {
132          printf("\033v");
133        }
134      #endif
135      #if defined( atarist ) || defined( NeXT )
136        struct sgttyb tattr;
137      #else
138        struct termios tattr;
139      #endif
140
141      /* Set the funny terminal modes. */
142      #ifdef atarist
143         gtty(0, &tattr);
144         tattr.sg_flags |= RAW;
145         tattr.sg_flags |= CBREAK;
146         tattr.sg_flags &= ~ECHO;
147         stty(0, &tattr);
148      #else
149        #ifdef NeXT
150          ioctl(STDIN_FILENO, TIOCGETP, &tattr);
151          //tattr.sg_flags |= RAW;
152          tattr.sg_flags |= CBREAK;
153          tattr.sg_flags &= ~ECHO;
154          ioctl(STDIN_FILENO, TIOCSETP, &tattr);
155          ioctl(STDOUT_FILENO, TIOCGETP, &tattr);
156          tattr.sg_flags |= CRMOD;
157          ioctl(STDOUT_FILENO, TIOCSETP, &tattr);
158        #else
159          tcgetattr (STDIN_FILENO, &tattr);
160          tattr.c_lflag &= ~(ICANON|ECHO); /* Clear ICANON and ECHO. */
161          tattr.c_cc[VMIN] = 1;
162          tattr.c_cc[VTIME] = 0;
163          tcsetattr (STDIN_FILENO, TCSAFLUSH, &tattr);
164        #endif
165      #endif
166      fe_is_raw_tty=1;
167    }
168  }
169#endif
170
171static char termcap_buff[2048];
172static int fe_out_char(char c)
173{
174  fputc(c,fe_echo);
175  return c;
176}
177void fe_init (void)
178{
179  #ifdef MSDOS
180  /*extern short ospeed;*/
181  #endif
182  fe_is_initialized=TRUE;
183  if ((!fe_use_fgets) && (isatty (STDIN_FILENO)))
184  {
185    /* Make sure stdin is a terminal. */
186    #ifndef MSDOS
187      char *term=getenv("TERM");
188
189      /*setup echo*/
190      if(isatty(STDOUT_FILENO))
191      {
192        fe_stdout_is_tty=1;
193        fe_echo=stdout;
194      }
195      else
196      {
197        fe_stdout_is_tty=0;
198        #ifdef atarist
199          fe_echo = fopen( "/dev/tty", "w" );
200        #else
201          fe_echo = fopen( ttyname(fileno(stdin)), "w" );
202        #endif
203      }
204
205      /* Save the terminal attributes so we can restore them later. */
206      {
207        #if defined( atarist ) || defined( NeXT )
208          struct sgttyb tattr;
209          #ifdef atarist
210            gtty(0, &fe_saved_attributes);
211          #else
212            ioctl(STDIN_FILENO, TIOCGETP, &fe_saved_attributes);
213          #endif
214        #else
215          struct termios tattr;
216          tcgetattr (STDIN_FILENO, &fe_saved_attributes);
217        #endif
218        #ifdef HAVE_ATEXIT
219          atexit(fe_reset_fe);
220        #else
221          on_exit(fe_reset_fe,NULL);
222        #endif
223
224      /* Set the funny terminal modes. */
225        #ifdef atarist
226          gtty(0, &tattr);
227          tattr.sg_flags |= RAW;
228          tattr.sg_flags |= CBREAK;
229          tattr.sg_flags &= ~ECHO;
230          stty(0, &tattr);
231        #else
232          #ifdef NeXT
233            ioctl(STDIN_FILENO, TIOCGETP, &tattr);
234            //tattr.sg_flags |= RAW;
235            tattr.sg_flags |= CBREAK;
236            tattr.sg_flags &= ~ECHO;
237            ioctl(STDIN_FILENO, TIOCSETP, &tattr);
238            ioctl(STDOUT_FILENO, TIOCGETP, &tattr);
239            tattr.sg_flags |= CRMOD;
240            ioctl(STDOUT_FILENO, TIOCSETP, &tattr);
241          #else
242            tcgetattr (STDIN_FILENO, &tattr);
243            tattr.c_lflag &= ~(ICANON|ECHO); /* Clear ICANON and ECHO. */
244            tattr.c_cc[VMIN] = 1;
245            tattr.c_cc[VTIME] = 0;
246            tcsetattr (STDIN_FILENO, TCSAFLUSH, &tattr);
247          #endif
248          /*ospeed=cfgetospeed(&tattr);*/
249        #endif
250      }
251    #endif
252    if(term==NULL)
253    {
254      printf("need TERM\n");
255    }
256    else if(tgetent(termcap_buff,term)<=0)
257    {
258      printf("could not access termcap data base\n");
259    }
260    else
261    {
262      extern char *BC;
263      extern char *UP;
264      extern char PC;
265      char *t_buf=(char *)Alloc(128);
266      char *temp;
267
268      /* Extract information that termcap functions use.  */
269      temp = tgetstr ("pc", &t_buf);
270      PC = (temp!=NULL) ? *temp : '\0';
271      BC=tgetstr("le",&t_buf);
272      UP=tgetstr("up",&t_buf);
273
274      /* Extract information we will use */
275      colmax=tgetnum("co");
276      pagelength=tgetnum("li");
277      fe_cursor_line=pagelength-1;
278
279      /* init screen */
280      temp = tgetstr ("ti", &t_buf);
281      if (temp!=NULL) tputs(temp,1,fe_out_char);
282
283      /* printf("TERM=%s, co=%d, li=%d\n",term,colmax,pagelength);*/
284    }
285
286    fe_stdin_is_tty=1;
287    fe_is_raw_tty=1;
288
289    /* setup history */
290    fe_hist=(char **)Alloc0(fe_hist_max*sizeof(char *));
291    fe_hist_pos=0;
292  }
293  else
294  {
295    fe_stdin_is_tty=0;
296    fe_echo=stdout;
297  }
298}
299
300/* delete to end of line */
301static void fe_ctrl_k(char *s,int i)
302{
303  int j=i;
304  while(s[j]!='\0')
305  {
306    fputc(' ',fe_echo);
307    j++;
308  }
309  while(j>i)
310  {
311    fputc('\b',fe_echo);
312    j--;
313  }
314}
315
316/* delete the line */
317static void fe_ctrl_u(char *s,int *i)
318{
319  fe_ctrl_k(s,*i);
320  while((*i)>0)
321  {
322    (*i)--;
323    fputc('\b',fe_echo);
324    fputc(' ',fe_echo);
325    fputc('\b',fe_echo);
326  }
327}
328
329/*2
330* add s to the history
331* if s is no the previous one, duplicate it
332*/
333static void fe_add_hist(char *s)
334{
335  if (s[0]!='\0') /* skip empty lines */
336  {
337    /* compare this line*/
338    if (fe_hist_pos!=0)
339    {
340      if ((fe_hist[fe_hist_pos-1]!=NULL)
341      && (strcmp(fe_hist[fe_hist_pos-1],s)==0))
342        return;
343    }
344    else
345    {
346      if ((fe_hist[fe_hist_max-1]!=NULL)
347      && (strcmp(fe_hist[fe_hist_max-1],s)==0))
348        return;
349    }
350    /* normal case: enter a new line */
351    /* first free the slot at position fe_hist_pos */
352    if (fe_hist[fe_hist_pos]!=NULL)
353    {
354      FreeL((ADDRESS)fe_hist[fe_hist_pos]);
355    }
356    /* and store a duplicate */
357    fe_hist[fe_hist_pos]=mstrdup(s);
358    /* increment fe_hist_pos in a circular manner */
359    fe_hist_pos++;
360    if (fe_hist_pos==fe_hist_max) fe_hist_pos=0;
361  }
362}
363
364static void fe_get_hist(char *s, int size, int *pos,int change, int incr)
365{
366  if (change)
367    fe_add_hist(s);
368  do
369  {
370    (*pos)+=incr;
371    if((*pos)>=fe_hist_max) (*pos)-=fe_hist_max;
372    else if((*pos)<0)       (*pos)+=fe_hist_max;
373  }
374  while (((*pos)!=0)&&(fe_hist[(*pos)]==NULL));
375  memset(s,0,size);
376  if (fe_hist[(*pos)]!=NULL)
377  {
378    strncpy(s,fe_hist[(*pos)],size-2);
379  }
380}
381
382static int fe_getchar()
383{
384  #ifndef MSDOS
385  char c='\0';
386  while (1!=read (STDIN_FILENO, &c, 1));
387  #else
388  int c=getkey();
389  #endif
390  #ifndef MSDOS
391  if (c == 033)
392  {
393    /* check for CSI */
394    c='\0';
395    read (STDIN_FILENO, &c, 1);
396    if (c == '[')
397    {
398      /* get command character */
399      c='\0';
400      read (STDIN_FILENO, &c, 1);
401      switch (c)
402      {
403        case 'D': /* left arrow key */
404          c = feCTRL('B')/*002*/;
405          break;
406        case 'C': /* right arrow key */
407          c = feCTRL('F')/*006*/;
408          break;
409        case 'A': /* up arrow key */
410          c = feCTRL('P')/*020*/;
411          break;
412        case 'B': /* down arrow key */
413          c = feCTRL('N')/*016*/;
414          break;
415      }
416    }
417  }
418  #endif
419  return c;
420}
421
422static void fe_set_cursor(char *s,int i)
423{
424  char tgoto_buf[40];
425  if (0)/*(fe_cursor_pos>1) && (i>0))*/
426  {
427    /*fputs(tgoto(tgetstr("cm",&tgoto_buf),fe_cursor_pos-1,fe_cursor_line),fe_echo);*/
428    tputs(tgoto(tgetstr("cm",&tgoto_buf),fe_cursor_pos-1,fe_cursor_line),
429      pagelength,fe_out_char);
430    fputc(s[i-1],fe_echo);
431  }
432  else
433  {
434    /*fputs(
435      tgoto(tgetstr("cm",&tgoto_buf),fe_cursor_pos,fe_cursor_line),fe_echo);*/
436    tputs(tgoto(tgetstr("cm",&tgoto_buf),fe_cursor_pos,fe_cursor_line),
437      pagelength,fe_out_char);
438  }
439  fflush(fe_echo);
440}
441
442char * fe_fgets_stdin_fe(char *pr,char *s, int size)
443{
444  if(!fe_is_initialized)
445    fe_init();
446  if (fe_stdin_is_tty)
447  {
448    int h=fe_hist_pos;
449    int change=0;
450    #ifdef MSDOS
451      int c;
452    #else
453      char c;
454    #endif
455    int i=0;
456
457    if (fe_is_raw_tty==0)
458    {
459      fe_temp_set();
460    }
461
462    fputs(pr,fe_echo); fflush(fe_echo);
463    fe_cursor_pos=strlen(pr); /* prompt */
464
465    memset(s,0,size);
466
467    loop
468    {
469      c=fe_getchar();
470      switch(c)
471      {
472        case feCTRL('M'):
473        case feCTRL('J'):
474        {
475          fe_add_hist(s);
476          i=strlen(s);
477          if (i<size-1) s[i]='\n';
478          fputc('\n',fe_echo);
479          fflush(fe_echo);
480          fe_temp_reset();
481          return s;
482        }
483        #ifdef MSDOS
484        case 0x153:
485        #endif
486        case feCTRL('H'):
487        case 127:       /*delete the character left of the cursor*/
488        {
489          if (i==0) break;
490          i--;
491          fe_cursor_pos--;
492          if(fe_cursor_pos<0)
493          {
494            fe_cursor_line--;
495            fe_cursor_pos=colmax-1;
496            fe_set_cursor(s,i);
497          }
498          else
499          {
500            fputc('\b',fe_echo);
501          }
502          /* NO BREAK : next: feCTRL('D') */
503        }
504        case feCTRL('D'):  /*delete the character under the cursor or eof*/
505        {
506          int j;
507          if ((i==0) &&(s[0]=='\0')) return NULL; /*eof*/
508          if (s[i]!='\0')
509          {
510            j=i;
511            while(s[j]!='\0')
512            {
513              s[j]=s[j+1];
514              fputc(s[j],fe_echo);
515              j++;
516            }
517            fputc(' ',fe_echo);
518            if (fe_cursor_pos+(j-i)>=colmax)
519            {
520              fe_set_cursor(s,i);
521            }
522            else
523            {
524              while(j>i)
525              {
526                fputc('\b',fe_echo);
527                j--;
528              }
529            }
530          }
531          #ifdef MSDOS
532          fputc('\b',fe_echo);
533          #endif
534          change=1;
535          fflush(fe_echo);
536          break;
537        }
538        case feCTRL('A'):  /* move the cursor to the beginning of the line */
539        {
540          if (i>=colmax-strlen(pr))
541          {
542            while (i>=colmax-strlen(pr))
543            {
544              i-=colmax;
545              fe_cursor_line--;
546            }
547            i=0;
548            fe_cursor_pos=strlen(pr);
549            fe_set_cursor(s,i);
550          }
551          else
552          {
553            while(i>0)
554            {
555              i--;
556              fputc('\b',fe_echo);
557            }
558            fe_cursor_pos=strlen(pr);
559          }
560          break;
561        }
562        case feCTRL('E'): /* move the cursor to the end of the line */
563        {
564          while(s[i]!='\0')
565          {
566            fputc(s[i],fe_echo);
567            i++;
568            fe_cursor_pos++;
569            if(fe_cursor_pos>=colmax)
570            {
571              fe_cursor_pos=0;
572              if(fe_cursor_line!=(pagelength-1))
573                fe_cursor_line++;
574            }
575          }
576          break;
577        }
578        case feCTRL('B'): /* move the cursor backward one character */
579        {
580          if (i>0)
581          {
582            i--;
583            fputc('\b',fe_echo);
584            fe_cursor_pos--;
585            if(fe_cursor_pos<0)
586            {
587              fe_cursor_pos=colmax-1;
588              fe_cursor_line--;
589            }
590          }
591          break;
592        }
593        case feCTRL('F'): /* move the cursor forward  one character */
594        {
595          if(s[i]!='\0')
596          {
597            fputc(s[i],fe_echo);
598            i++;
599            fe_cursor_pos++;
600            if(fe_cursor_pos>=colmax)
601            {
602              fe_cursor_pos=0;
603              if(fe_cursor_line!=(pagelength-1))
604                fe_cursor_line++;
605            }
606          }
607          break;
608        }
609        case feCTRL('U'): /* delete entire input line */
610        {
611          fe_ctrl_u(s,&i);
612          fe_cursor_pos=strlen(pr);
613          memset(s,0,size);
614          change=1;
615          break;
616        }
617        #if 0
618        case feCTRL('W'): /* test hist. */
619        {
620          int i;
621          PrintS("\nstart hist\n");
622          for(i=0;i<fe_hist_max;i++)
623          {
624            if(fe_hist[i]!=NULL)
625            {
626              Print("%2d ",i);
627              if(i==fe_hist_pos) PrintS("-"); else PrintS(" ");
628              if(i==h) PrintS(">"); else PrintS(" ");
629              PrintS(fe_hist[i]);
630              PrintLn();
631            }
632          }
633          Print("end hist, next_pos=%d\n",fe_hist_pos);
634          break;
635        }
636        #endif
637        case feCTRL('K'): /* delete up to the end of the line */
638        {
639          fe_ctrl_k(s,i);
640          memset(&(s[i]),'\0',size-i);
641          /* s[i]='\0';*/
642          change=1;
643          break;
644        }
645        case feCTRL('L'): /* redraw screen */
646        {
647          char t_buf[40];
648          char *t=t_buf;
649          fe_cursor_line=i/colmax;
650          /*fputs(tgetstr("cl",&t),fe_echo);*/
651          tputs(tgetstr("cl",&t),pagelength,fe_out_char);
652          fflush(fe_echo);
653          fputs(pr,fe_echo);
654          fputs(s,fe_echo);
655          fe_set_cursor(s,i);
656          break;
657        }
658        case feCTRL('P'): /* previous line */
659        {
660          fe_ctrl_u(s,&i);
661          fe_get_hist(s,size,&h,change,-1);
662          while(s[i]!='\0')
663          {
664            fputc(s[i],fe_echo);
665            i++;
666          }
667          fe_cursor_pos=strlen(pr)+i/*strlen(s)*/;
668          change=0;
669          break;
670        }
671        case feCTRL('N'): /* next line */
672        {
673          fe_ctrl_u(s,&i);
674          fe_get_hist(s,size,&h,change,1);
675          while(s[i]!='\0')
676          {
677            fputc(s[i],fe_echo);
678            i++;
679          }
680          fe_cursor_pos=strlen(pr)+i/*strlen(s)*/;
681          change=0;
682          break;
683        }
684        default:
685        {
686          if ((c>=' ')&&(c<=126))
687          {
688            fputc (c,fe_echo);
689            fe_cursor_pos++;
690            if(fe_cursor_pos>=colmax)
691            {
692              fe_cursor_pos=0;
693              if(fe_cursor_line!=(pagelength-1))
694                fe_cursor_line++;
695            }
696            if (s[i]!='\0')
697            {
698              /* shift by 1 to the right */
699              int j=i;
700              int l;
701              while ((s[j]!='\0')&&(j<size-2)) j++;
702              l=j-i;
703              while (j>i) { s[j]=s[j-1]; j--; }
704              /* display */
705              fwrite(s+i+1,l,1,fe_echo);
706              fflush(fe_echo);
707              /* set cursor */
708              if(fe_cursor_pos+l>=colmax)
709              {
710                while(fe_cursor_pos+l>=colmax)
711                {
712                  fe_cursor_line--;
713                  l-=colmax;
714                }
715                fe_set_cursor(s,i);
716              }
717              else
718              {
719                while(l>0)
720                {
721                  l--;
722                  fputc('\b',fe_echo);
723                }
724              }
725              fflush(fe_echo);
726            }
727            if (i<size-1) s[i]=c;
728            i++;
729            change=1;
730          }
731        }
732      } /* switch */
733      fflush(fe_echo);
734    } /* loop */
735  }
736  /*else*/
737    return fgets(s,size,stdin);
738}
739
740//int main (void)
741//{
742//  char b[200];
743//  char * m_eof;
744//
745//  fe_init();
746//  while(1)
747//  {
748//    m_eof=fe_fgets_stdin_fe("> ",b,200);
749//    if (!m_eof) break;
750//    printf(">>%s<<\n",b);
751//  }
752//
753//  return 0;
754//}
755#endif
Note: See TracBrowser for help on using the repository browser.