source: git/Singular/fereadl.c @ 6f83c3d

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