source: git/Singular/fereadl.c @ c232af

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