source: git/Singular/fereadl.c @ c4bb5a6

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