source: git/Singular/fereadl.c @ f058c1b

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