source: git/Singular/fereadl.c @ 457d8d6

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