source: git/Singular/fereadl.c @ ec595fe

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