source: git/Singular/fereadl.c @ 3037783

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