#include "all.h"
#include <errno.h>
#include <math.h>

#ifdef __TURBOC__
        #define HLINECHAR 205
        #include "bios.h"
        #include "conio.h"
#elif DJ                                                /* a.r. */
        #define ENOFILE 999
        #define HLINECHAR 205
        #define clrscr ScreenClear
#elif EMXOS2                                            /* a.r. */
        #include <sys/video.h>
        #define ENOFILE 999
        #define HLINECHAR 205
        extern unsigned long startPMSession(void);
        extern unsigned long stopPMSession(unsigned long SessID);
        unsigned long oldSession = 0;
        extern int g_get_type(char *t);
        int text_saveOS2tmp(void);
        char devtype[60];
        #ifdef SURFACE
        char outputName[80];  
        #endif
#else
        #define ENOFILE 999
        #define HLINECHAR '-'
        #include "vaxconio.h"
#endif

#include "edt.h"

int vax_edt(char *s);
int delay(int i);
extern int gle_debug;
int gle_speed;
int gle_nspeed;
int trace_on;
#define true (!false)
#define false 0
#define dbg if (gle_debug>0)
int32 mem_total(void);
int pick_file(char *r, char *w);
typedef char (*TEXT)[];
int scr_blackwhite;
int scr_left(int i);
int scr_right(int i);
int scr_norm(void);
int scr_inv(void);
int scr_grey(void);
int text_search(void);
int text_deleol(void);
int text_undeleol(void);
int scr_savexy(void);
int scr_restorexy(void);
int scr_gets(char *s);
int text_showerror(void);
int text_findnext(void);
int text_changed(void);
int read_command(char *ans, char *ques);
int read_str(char *s);
int text_load(char *fname);
int text_free(void);
int do_help(char *s);
int int_edt(char *fname);
int vinsert(int y, char *s);
int vdelete(int y);
int menu(void);
int gle_redraw(void);
int scrinsert(int y);
int scrdeleteline(int y);
int text_save(void) ;
int text_eol(void);
int text_delright(void);
int text_delete(void);
int text_undelete(void);
int text_deleteline(void);
int text_left(void);
int text_right(void);
int text_up(void);
int text_down(void);
int text_return(void);
int text_refresh();
int text_putstr(char *s);
int text_setwindow();
int text_saveas(void);
int text_move(int x,int y);
int scr_tab(char *s, int x);
int scr_negtab(char *s, int x, int *fpos, int *scrx);
int fner(char *s);
int fner_clear(void);
int text_setwindow(void);
int text_refresh(void);
int text_main(void);
int text_inkey(void);
int text_scroll(void);
int text_scroll_up(void);
int text_scroll_down(void);
int text_select(void);
int text_cut(void);
int text_paste(void);
int restofline(int y,int x);
int normal_key(int c);
int lineset(int i,char *ss);
int lineinsert(int y, char *ss);
int textinsert(int y);
char *sline(int i);
char *line(int i);
int ncpy(char *d, char *s, int n);
/*------------ GLOBAL VARIABLES --------------*/
extern int32 gtotalmem;
int max_ngtxt;
extern int ngtxt;
extern char *(*gtxt)[];   /* gtxt is a pointer to an array of poiter to char */
char *(*ctxt)[];    /* cut buffer */
int ncut;
int iserr;
int w_top=0,w_bot=0,w_len,w_cl,w_cx;
#define MAXLINES (max_ngtxt-10)
extern int ngtxt;
int move_pos,onmove;
int ii;
char gbuff[255];
char gbuff2[255];
int selx,sely;
extern char input_file[];
int changed;
int scr_isblackwhite(void);
extern int netxt;   /* errors which occured */
extern char *(*etxt)[];
/*---------------------------------------------------------------------------*/
/* copy gtxt, ngtxt   to local paramters */
int tfx,tfy;
extern int gotfile;
int_edt(char *fname)
{
        int i,j;

        tfx = 1;
        tfy = 1;

#ifdef  EMXOS2                                  /* a.r. */
        w_len = 22;
#else
        w_len = 20;
#endif
        scr_blackwhite = scr_isblackwhite();
        if (!gotfile) {
                { char infile[80]; char wildcard[80];
        #ifdef SURFACE
                strcpy(wildcard,"*.sur");
                if (pick_file(infile,wildcard)) strcpy(infile,"test.sur");
        #else
                strcpy(wildcard,"*.gle");
                if (pick_file(infile,wildcard)) strcpy(infile,"test.gle");
        #endif
                text_load(infile);
                }
        }
        gotfile=true;
        text_setwindow();
        text_refresh();
        text_main();
}
vinsert(int y,char *ss)
{
        int i;
        if (ngtxt>(max_ngtxt-50)) text_expand(2*(ngtxt+50));
        if (ngtxt>MAXLINES) {fner("too many lines in file "); return;}
        ngtxt++;
        for (i=ngtxt;i>y;i--)
                (*gtxt)[i] = (*gtxt)[i-1];
        (*gtxt)[y] = sdup(ss);
}
lineinsert(int y,char *ss)
{
        vinsert(y,ss);
        scrinsert(y);
}

vdelete(int y)
{
        int i;
        if (ngtxt==0) {fner("too few lines in file "); return;}
        ngtxt--;
        myfrees((*gtxt)[y],"vdelete");
        for (i=y;i<=ngtxt;i++)
                (*gtxt)[i] = (*gtxt)[i+1];
}
linedelete(int y)
{
        vdelete(y);
        scrdeleteline(y);
}
lineset(int i,char *ss)
{
        char *zzz;
        int same;
        char *d=(*gtxt)[i];
        char *s=ss;
        if (d==0) gle_abort("linset zero\n");
        for (;*d!=0 && *s!=0 && *d==*s ;s++,d++) ;
        same = s-ss;
        myfrees((*gtxt)[i],"Linset");
        zzz = sdup(ss);
        (*gtxt)[i] = zzz;
        restofline(i,same);
}
char *line(int i)
{
        static char xxx[2]="";
        static char eob[7]="[EOB]";
        if (i>ngtxt) {
                if (i==ngtxt+1) return &eob[0];
                else return &xxx[0];
        }
        return (*gtxt)[i];
}
text_free(void)
{
        int i;
        for (i=1;i<=ngtxt;i++) myfrees( (*gtxt)[i] ,"textfree");
        ngtxt = 0;
}
char *tabtospace(char *s);
char *sline(int i)
{
        char *s;
        s = tabtospace(line(i));
        if (strlen(s)>77) {s[77] = '>'; s[78] = 0;}
        return s;
}
char *tabtospace(char *s)
{
        static char buf[255];
        char *o = &buf[0];
        int p=0,k,df;
        for (;*s!=0;s++) {
                if (*s==9) {
                        df = (p/8)*8+8-p;
                        for (k=1;k<=df;k++) {
                                *o++ = ' ';
                                p++;
                        }
                } else {
                        *o++ = *s;
                        p++;
                }
        }
        *o = 0;
        return &buf[0];
}
text_main()
{
        int c,doask;
        for (;;) {
         doask = true;
         c = text_inkey();
         if (iserr) fner_clear();
         switch (c) {
           case eexitnow:
                doask = false;
           case eescape:
           case equit: /* control c */
                if (text_changed()) break;
                if (doask) {
                  #ifdef SURFACE
                  fner("Exit from Surface ? (Y,N)  [y]");
                  #else
                  fner("Exit from GLE ? (Y,N)  [y]");
                  #endif
                  c = text_inkey();
                  fner_clear();
                  if (tolower(c)=='n') break;
                  if (tolower(c)!='y' && c != ereturn) break;
                }
                window(1,1,80,25);
                scr_norm();
                clrscr();
                return;
           case eedt: /* call edt editor */
                text_save();
                clrscr();
                fner("Entering VAX EDT");
                scr_refresh();
                vax_edt(input_file);
                text_free();
                text_load(input_file);
                text_setwindow();
                text_refresh();
                break;
           case efast:
                gle_speed++;
                if (gle_speed>=gle_nspeed) gle_speed = 0;
                sprintf(gbuff,"Speed of display set to {%d}",gle_speed);
                fner(gbuff);
                break;
           case eleft: /* left */
                text_left();
                break;
           case eshell: /* shell, start a subprocess */
                window(1,1,80,25); scr_norm(); clrscr();
                #ifdef SURFACE
                printf("Type in EXIT to return to Surface\n\n");
                #else
                printf("Type in EXIT to return to GLE\n\n");
                #endif
                #ifndef DJ                                      /* a.r. */
                system("");
                #else
                system(getenv("COMSPEC"));
                #endif
                text_refresh();
                break;
           case etrace: /* trace */
                fner("Trace is now ON (or off)");
                if (trace_on) trace_on = false; else trace_on = true;
                break;
           case eright: /* right */
                text_right();
                break;
           case eup: /* arrow up */
                text_up();
                break;
           case edown: /* arrow down */
                text_down();
                break;
           case epageup:
                tfy = tfy - 15;
                if (tfy<1) {fner("Backup past top of file"); tfy = 1;}
                text_move(tfx,tfy);
                break;
           case epagedown:
                tfy = tfy + 15;
                if (tfy>ngtxt) {fner("Advance past end of file"); tfy = ngtxt;}
                text_move(tfx,tfy);
                break;
           case edelright:
                changed = true;
                text_right();
                text_delete();
                break;
           case edeleol:
                changed = true;
                text_deleol();
                break;
           case eundeleol:
                changed = true;
                text_undeleol();
                break;
           case edelline:
                changed = true;
                text_deleteline();
                break;
          case edrawit:
                window(1,1,79,24);
                clrscr();
                gotoxy(1,1);
                scr_refresh();
               #ifndef EMXOS2                           /* a.r. */
                gle_redraw();
                if (netxt>0) text_showerror();
                text_refresh();
               #else
                g_get_type(devtype);
                if (strstr(devtype, "HARDCOPY") == NULL)
                       {
                        #ifdef SURFACE
                        strcpy(outputName, input_file);
                        #endif
                        if ( oldSession != 0 ) 
                                stopPMSession(oldSession);
                        text_saveOS2tmp();
                        text_refresh();
                        oldSession = startPMSession();
                       }
                else
                       {
                        gle_redraw();
                        if (netxt>0) text_showerror();
                        text_refresh();
                       }
               #endif
                break;
          case eshowerror:
                text_showerror();
                text_refresh();
                break;
          case eundelline:
                changed = true;
                text_undelete();
                break;
          case eselect:
                text_select();
                break;
          case ehelp: /* help */
                     #ifdef SURFACE
                     do_help("SURFACE");
                #else
                do_help2("gle");
                #endif
                text_refresh();
                break;
          case esaveas:
                text_saveas();
                text_refresh();
                break;
          case esave: /* save file */
                text_save();
                changed = false;
                break;
          case efindnext:
                text_findnext();
                break;
          case esearch: /* search for string */
                text_search();
                break;
          case egraphmenu: /* graph mode  */
                changed = true;
                menu();
                text_refresh();
                break;
          case eload:
                { char infile[80]; char wildcard[80];
                if (text_changed()) break;
                if (read_command(infile,"Name of file to load <return for menu> ")) break;
                strcpy(wildcard,infile);
                #ifdef SURFACE
                if (strlen(infile)==0) strcpy(wildcard,"*.sur");
                #else
                if (strlen(infile)==0) strcpy(wildcard,"*.gle");
                #endif
                if (strchr(wildcard,'*')!=NULL)
                        if (pick_file(infile,wildcard)) goto dontload;
                text_free();
                text_load(infile);
                }
                text_setwindow();
dontload:   text_refresh();
                break;
          case ecut: /* control K , delete line, or block */
                changed = true;
                text_cut();
                break;
          case emark: /* quick hack a.r. */
                changed = true;
                text_cut();
                text_paste();
                break;
          case ebol:
                text_move(1,tfy);
                break;
          case eeol:
                text_move(strlen(line(tfy))+1,tfy);
                break;
          case eendoffile:
                text_move(strlen(line(ngtxt))+1,ngtxt);
                break;
          case etopoffile:
                text_move(1,1);
                break;
          case epaste: /* control Y , Yank line back, or block */
                changed = true;
                text_paste();
                break;
          case ereturn: /* carriage return */
                changed = true;
                text_return();
                break;
          case edelete: /* delete */
                changed = true;
                text_delete();
                break;
          default: /* normal key */
                changed = true;
                onmove = false;
                if (c<26  && c!=9) {fner("Key has no affect"); text_move(tfx,tfy); break;}
                if (c>200)  {fner("Unimplemented command"); text_move(tfx,tfy);}
                else normal_key(c);
                break;
         }
        }
}
text_changed()
{
        int c;
        if (!changed) return false;
        for (;;) {
                fner("Save changes ? (Y,N)");
                c = text_inkey();
                fner_clear();
                if (c==eescape) return true;
                if (tolower(c)=='n') return false;
                if (tolower(c)=='y') {text_save(); return false;}
        }
}
int text_expand(int n);
text_expand(int n)
{
        char **a;
        max_ngtxt = n;
        a = myallocz((n+1)*sizeof(char *));
        if (gtxt!=NULL) {
                memcpy(a,gtxt,(ngtxt+1)*sizeof(char *));
                myfrees(gtxt,"textexpand");
        }
        gtxt = (char *(*)[]) a;
}
text_load(char *fname)
{
static char inbuff[200];
FILE *fptr;
char *s;
int i;
char emess[80];
        changed = false;
        strcpy(input_file,fname);
        s = strchr(input_file,'.');
        #ifdef SURFACE
        if (s==NULL) strcat(input_file,".sur");
        #else        
        if (s==NULL) strcat(input_file,".gle");
        #endif
        fptr = fopen(input_file,"r");
        if (fptr==NULL) 
           {
                if (errno == ENOFILE) 
                  {
                   sprintf(emess,"Input file does not exist (%s) ",input_file);
                   fner(emess);
                   delay(1000);
                  }
                else
                      {
                       #if (defined EMXOS2 && defined SURFACE)
                        fprintf(stderr, "Unable to open input file {%s} \n",input_file);
                       #else
                        gprint("Unable to open input file {%s} \n",input_file);
                       #endif
                        perror("Reason");
                        fner("Press return to continue");
                        text_inkey();
                      }
           }
        else 
           {
            for (;!feof(fptr);)
               {
                if (fgets(inbuff,200,fptr)!=NULL)
                   {
                        i = strlen(inbuff);
                        if (inbuff[i-1]=='\n') inbuff[i-1] = 0;
                        ngtxt++;
                        if (ngtxt>(max_ngtxt-300)) {
                                text_expand(2*(ngtxt+500));
                        }
                        (*gtxt)[ngtxt] = myalloc(i+1);
                        strcpy((*gtxt)[ngtxt],inbuff);
                   }
               }
         fclose(fptr);
        }
        #ifdef SURFACE
        if (ngtxt==0) 
           {
                (*gtxt)[++ngtxt] = sdup("begin surface");
                (*gtxt)[++ngtxt] = sdup("   data test.z");
                (*gtxt)[++ngtxt] = sdup("end surface");
           }
        #else
        if (ngtxt==0) (*gtxt)[++ngtxt] = sdup("size 24 18");
        #endif
        if (ngtxt==1) (*gtxt)[++ngtxt] = sdup("");
        tfx = 1;
        tfy = 1;
}
char errgle[90];
int dont_clear;
gle_abort(char *s)
{
        printf("%s",s); scr_refresh();
        d_tidyup();
        delay(1000);
        dont_clear = true;
        window(1,1,80,25);
        scr_norm();
        clrscr();
        #ifdef SURFACE
        printf("\n\n\n\n %s \nSurface is aborting, Attempting to save file in abort.gle\n",s);
        #else
        printf("\n\n\n\n %s \nGLE is aborting, Attempting to save file in abort.gle\n",s);
        #endif
        strcpy(input_file,"abort.gle");
        text_save();
        printf("File is now saved (hopefully)\n");
        if (strstr(s,"alloc")!=NULL  || strstr(s,"Init")!=NULL) {
                   #ifdef SURFACE
                printf("\nSurface is short of memory!!\n\n");
                #else
                printf("\nGLE is short of memory!!\n\n");
                #endif
                printf("If you are using very large datasets you should try\n");
                printf("the BIGFILE option, otherwise you probably have too\n");
                printf("many memory resident programs on your pc and to make GLE work\n");
                printf("you should remove these from your CONFIG.SYS and AUTOEXEC.BAT\n");
                printf("\n  (make copies of these files before altering them)\n");
        }
        scr_refresh();
        scr_end();
        exit(1);
}
text_save()
{
static int tver=0;
char tbuf[15];
FILE *fptr;
int i;
        changed = false;
        fner("Saving file");
#if (defined __TURBOC__ || defined DJ)
        if (input_file[1] == ':') setdisk(toupper(input_file[0])-'A');
#endif
#ifdef EMXOS2                                           /* a.r. */
        if (input_file[1] == ':')
                DosSetDefaultDisk(toupper(input_file[0])-'A' + 1);
#endif
        tver++; if (tver==5) tver=1;
        sprintf(tbuf,"gletmp.t%d",tver);
        unlink(tbuf);
        unlink("glegle.tmp");
#ifdef VAXC
#include <file.h>
{
int file_desc;
        file_desc = open("glegle.tmp",O_WRONLY | O_CREAT | O_TRUNC ,0,"rat=cr","rfm=var");
        if (file_desc==-1) { gprint("Open glegle.tmp error \n");  return;}
        fptr = fdopen(file_desc,"w");
}
#else
        fptr = fopen("glegle.tmp","w");
#endif
        if (fptr==NULL) perror("Unable to open output file GLEGLE.TMP");
        for (i=1;i<=ngtxt;i++) {
                if (fputs(line(i),fptr)==EOF
                        && i<ngtxt &&  (strlen(line(i)) > 0) )
                        printf("Unable to write line %d {%s} \n",i,line(i));
                fputs("\n",fptr);
        }
        if (fclose(fptr)!=0) perror("Unable to close output file GLEGLE.TMP");
#ifndef VMS
        if (rename(input_file,tbuf)!=0) ; /*
                perror("Unable to rename input file to gletmp.t*"); */
#endif
#ifdef EMXOS2                                   /* a.r. */
#ifdef SURFACE
        unlink(input_file);
#endif
#endif
        if (rename("glegle.tmp",input_file)!=0)
           perror("Unable to rename GLEGLE.TMP to output file");
        fner_clear();
}
text_bol()
{
        tfx = 1;
        /*        text_move(tfx,tfy);         in surf !! */
}
text_eol()
{
        tfx = strlen(line(tfy))+1;
        text_move(tfx,tfy);
}
text_left()
{
        onmove = false;
        if (tfx==1) {
                if (tfy==1) return;
                tfy--; tfx = strlen(line(tfy))+1;
        } else tfx--;
        text_move(tfx,tfy);
}
text_right()
{
        onmove = false;
        if (tfx== 1+strlen(line(tfy)) ) {
                if (tfy==ngtxt) return;
                tfy++; tfx = 1;
        } else tfx++;
        text_move(tfx,tfy);
}
text_up()
{
        if (tfy==1) {fner("Backup past end of file"); text_move(tfx,tfy); return;}
        if (!onmove) {
                onmove = true;
                move_pos = scr_tab(line(tfy),tfx);
        }
        tfy--;
        scr_negtab(line(tfy),move_pos,&tfx,&ii);
        text_move(tfx,tfy);
}
text_down()
{
        if (tfy==ngtxt) {fner("Advance past end of file"); tfy--;}
        if (!onmove) {
                onmove = true;
                move_pos = scr_tab(line(tfy),tfx);
        }
        tfy++;
        scr_negtab(line(tfy),move_pos,&tfx,&ii);
 /*gotoxy(5,9);gprint("negtab line=%d m=%d f=%d \n",tfy,move_pos,tfx);*/
        text_move(tfx,tfy);
}
text_return()
{
        strcpy(gbuff,line(tfy)+tfx-1);
        ncpy(gbuff2,line(tfy),tfx-1);
        lineset(tfy,gbuff2);
        lineinsert(tfy+1,gbuff);
        text_right();
}
char line_buff[255];
text_undelete()
{
        lineinsert(tfy,line_buff);
        text_move(tfx,tfy);
}
text_undeleol()
{
        strcpy(gbuff2,line(tfy)+tfx-1);
        ncpy(gbuff,line(tfy),tfx-1);
        strcat(gbuff,line_buff);
        lineinsert(tfy,gbuff);
        lineset(tfy+1,gbuff2);
        text_move(tfx,tfy);
}
text_saveas()
{
        char *s;
        #ifdef SURFACE
        if (read_command(input_file,"New Surface file name ")) return;
        #else
        if (read_command(input_file,"New GLE file name ")) return;
        #endif
        s = strchr(input_file,'.');
        #ifdef SURFACE
        if (s==NULL) strcat(input_file,".sur");
        #else
        if (s==NULL) strcat(input_file,".gle");
        #endif
        text_save();
}
#ifdef EMXOS2
text_saveOS2tmp()                                       /* a.r. */
{
           #ifdef SURFACE
                       #define TEMPFILENAME "surfos2.tmp"
           #else
                       #define TEMPFILENAME "gleos2.tmp"
           #endif

        FILE *fptr;
        int i;

        unlink(TEMPFILENAME);
        fptr = fopen(TEMPFILENAME,"w");
        if (fptr==NULL) perror("Unable to open output file GLEOS2.TMP");
        for (i=1;i<=ngtxt;i++) {
                if (fputs(line(i),fptr)==EOF
                        && i<ngtxt &&  (strlen(line(i)) > 0) )
                        printf("Unable to write line %d {%s} \n",i,line(i));
                fputs("\n",fptr);
        }
        if (fclose(fptr)!=0) perror("Unable to close output file GLEOS2.TMP");
}
#endif

char search_string[100];
text_search()
{
        if (read_command(search_string,"Enter string to search for ")) return;
        strlwr(search_string);
        text_findnext();
}
text_findnext()
{
        int i;
        char fline[100];
        char *p;
        for (i=tfy+1; i<=ngtxt; i++) {
                ncpy(fline,line(i),90);
                strlwr(fline);
                p = strstr(fline,search_string);
                if (p!=NULL) {
                        tfy = i; tfx = p - &fline[0] + 1;
                        text_move(tfx,tfy);
                        return;
                }
        }
        fner("String was not found");
}
text_select()
{
        selx = tfx; sely = tfy;
        text_move(tfx,tfy);
}
int swapint(int *a,int *b);
swapint(int *a, int *b)
{
        int c;
        c = *a; *a = *b; *b = c;
}
text_cut()
{
        int i,x1=selx,y1=sely,x2=tfx,y2=tfy;
        if (selx==0 && sely==0) return;
        if (y1==y2)  if (x2<x1) swapint(&x1,&x2);
        if (y2<y1) { swapint(&x1,&x2); swapint(&y1,&y2); }
        if (ncut>0) {
                myfrees(ctxt,"textcut");
                for (i=1;i<=ncut;i++) myfree((*ctxt)[i]);
        }
        ctxt = myalloc((y2-y1+3)*sizeof(char *));
        ncut = 1;
        if (y1==y2) {
                ncpy(gbuff,line(y1)+x1-1,x2-x1);
                (*ctxt)[1] = sdup(gbuff);
                ncpy(gbuff,line(y1),x1-1);
                strcat(gbuff,line(y1)+x2-1);
                lineset(y1,gbuff);
                text_move(x1,y1);
                return;
        }
        for (i=y1+1;i<y2;i++) (*ctxt)[++ncut] = sdup(line(i));
        for (i=y1+1;i<y2;i++) linedelete(y1+1);
        (*ctxt)[1] = sdup(line(y1)+x1-1);
        ncpy(gbuff2,line(y1+1),x2-1);
        (*ctxt)[++ncut] = sdup(gbuff2);
        ncpy(gbuff,line(y1),x1-1);
        strcat(gbuff,line(y1+1)+x2-1);
        lineset(y1,gbuff);
        linedelete(y1+1);
        text_move(x1,y1);
}
text_paste()
{
        int i;
        if (ncut==0) return;
        if (ncut==1) {
                ncpy(gbuff,line(tfy),tfx-1);
                strcat(gbuff,(*ctxt)[1]);
                strcat(gbuff,line(tfy)+tfx-1);
                lineset(tfy,gbuff);
                text_move(tfx+strlen((*ctxt)[1]),tfy);
                return;
        }
        ncpy(gbuff,line(tfy),tfx-1);
        strcat(gbuff,(*ctxt)[1]);
        strcpy(gbuff2,(*ctxt)[ncut]);
        strcat(gbuff2,line(tfy)+tfx-1);
        lineset(tfy,gbuff);
        lineinsert(tfy+1,gbuff2);
        for (i=ncut-1;i>1;i--) lineinsert(tfy+1, (*ctxt)[i]);
        text_move(strlen((*ctxt)[ncut])+1,tfy+ncut-1);
}
text_deleol()
{
        if (ngtxt+1==tfy) return;
        strcpy(line_buff,line(tfy)+tfx-1);
        ncpy(gbuff,line(tfy),tfx-1);
        if (tfy<ngtxt) strcat(gbuff,line(tfy+1));
        lineset(tfy,gbuff);
        if (ngtxt<=tfy) {
                gbuff[0] = 0;
                lineinsert(tfy+1,gbuff);
        } else  linedelete(tfy+1);
        text_move(tfx,tfy);
}
text_deleteline()
{
        if (ngtxt==1) return;
        strcpy(line_buff,line(tfy));
        linedelete(tfy);
        if (ngtxt<tfy) {
                gbuff[0] = 0;
                lineinsert(tfy,gbuff);
        }
        text_move(tfx,tfy);
}
text_delete()
{
        int oldx;
        if (tfx==1) {
                if (tfy==1) {fner("Backup past top of file"); return;}
                text_left();
                oldx = tfx;
                strcpy(gbuff2,line(tfy));
                text_deleteline();
                strcat(gbuff2,line(tfy));
                lineset(tfy,gbuff2);
                tfx = oldx;
                text_move(tfx,tfy);
                return;
        }
        ncpy(gbuff,line(tfy),tfx-2);
        strcat(gbuff,line(tfy)+tfx-1);
        tfx--;
        lineset(tfy,gbuff);
        text_move(tfx,tfy);
}
text_setwindow()
{
        if (tfy>w_top-4 || tfy<w_bot+4) w_top = tfy - (w_len-1)/2;
        if (w_top<1) w_top = 1;
        w_bot = w_top + w_len - 1;
}
text_refresh()
{
        char doubleline[90];
        int e,i;
        iserr = true; /* so that function keys appear at bottom */
        window(1,1,80,25);
        scr_norm();
        clrscr();
        #ifdef SURFACE
        gotoxy(1,1); wprintf("Memory Used=%ld  Free=%ld   Surface V3.3h Current file={%s}"
                ,mem_total(),coreleft(),input_file);
        #else
        gotoxy(1,1); wprintf("Memory Used=%ld  Free=%ld   GLE V3.3h  Current file={%s}"
                ,mem_total(),coreleft(),input_file);
        #endif

        memset(doubleline,HLINECHAR,80);
        doubleline[78] = 0;
        gotoxy(1,2); cputs(doubleline);

        fner_clear();


       #if ( defined DJ || defined EMXOS2 )                     /* a.r. */
        window(2,3,79,24);
       #else
        window(2,3,79,23);
       #endif

        gotoxy(1,1);
        e = w_bot;
        if (e>ngtxt) e = ngtxt;
        for (i=w_top;i<=e;i++) {
                gotoxy(1,i-w_top+1);
                cputs( sline(i) );
        }
        if (e<w_bot) {
                gotoxy(1,i-w_top+1);
                cputs("[EOF]");
        }
        gotoxy(scr_tab(line(tfy),tfx), tfy - w_top + 1);
}
/*---------- move cursor to file coloumn x, line y */
text_move(int x,int y)
{
        tfx = x;
        tfy = y;
        if (tfy>ngtxt) tfy = ngtxt;
        if (tfy<1) tfy = 1;
/*  if (tfx>79) tfx = 79; */
        if (tfx>strlen(line(tfy))+1) tfx = strlen(line(tfy))+1;
        if (tfx<1) tfx = 1;
        if (tfy<(w_top+5) || tfy>(w_bot-5)) {
                if (tfy<(w_top-25) || tfy>(w_bot+25)) {
                        text_setwindow();
                        text_refresh();
                } else {
                        text_scroll();
                }
        }
        gotoxy(scr_tab(line(tfy),tfx), tfy - w_top + 1);
}
restofline(int y,int x)
{
        int sx;
        if (x <= strlen(line(y))) {
                sx = scr_tab(line(y),x);
                gotoxy(sx,y-w_top + 1);
                clreol();
                cputs(sline(y)+sx-1);
                gotoxy(scr_tab(line(y),tfx), y - w_top + 1);
        }
}
fixline(int y)
{
        gotoxy(1,y-w_top + 1);
        clreol();
        cputs(sline(y));
}
scrinsert(int y)
{
#ifndef EMXOS2                                  /* a.r. */
#ifdef DJ
        if (y-w_top + 1 >= w_len ) 
               {
                text_refresh();
                return;
               }
#endif
        gotoxy(1,y-w_top + 1);
        insline();
        cputs(sline(y)); clreol();
#else
        v_scroll( 0, y - w_top + 2, 79, 23, 1, V_SCROLL_DOWN );
        gotoxy(1, y-w_top);      clreol();
        gotoxy(1, y-w_top);      cputs(sline(y-1));
        gotoxy(1, y-w_top + 1);  cputs(sline(y));
#endif
#ifdef DJ                                       /* a.r. */
        gotoxy(1,y-w_top + 2);
        cputs(sline(y+1));
        gotoxy(1,y-w_top + 1);
#endif
}
text_scroll()
{
        int n,i;
        n = w_top - tfy + 5;
        /* printf("n %d, w_top %d  tfy %d \n",n,w_top,tfy); */
        if (w_top-n<1) n = w_top - 1;
        if (n>0) {
                for (i=0;i<n;i++) text_scroll_down();
                return;
        }
        n = tfy - w_bot + 5;
        if (w_bot+n>ngtxt) n = ngtxt - w_bot;
        if (n>0) {
                for (i=0;i<n;i++) text_scroll_up();
                return;
        }
}
/* ------------------------ Find screen position given x pos in string */
scr_tab(char *s, int x)
{
        int p=0,i=0;
        for (;*s!=0 && i<(x-1);i++,s++) {
                if (*s==9)  p = (p/8)*8+8;
                else       p++;
        }
        if (p>= 77) p = 77;
        return ++p;
}
/*------------------------- Find file x position given x pos on screen */
/* and sets scrx to the correct screen position (if in middle of tab) */
scr_negtab(char *s, int x, int *fpos, int *scrx)
{
        int last_pos=0,i;
        *fpos=0;
        *scrx = 0;

        for (i=0;*s!=0;s++,i++) {
                if (*s==9) *scrx = (*scrx/8)*8+8;
                else (*scrx)++;
                if ((*scrx+1)>x) {
                        *fpos = i+1;
                        *scrx = last_pos;
                        return;
                }
                last_pos = *scrx + 1;
        }
        if (*scrx==0) (*scrx)++;
        *fpos = i+1;
        if (i==0) *fpos = 1;
}
text_scroll_down()
{
#ifndef EMXOS2                                          /* a.r. */
 #ifdef __TURBOC__
        window(2,3,79,22);
 #endif
 #ifdef DJ                                               /* a.r. */
        window(2,3,79,24);
 #endif

        gotoxy(1,1);insline();

 #ifdef __TURBOC__
        window(2,3,79,23);
 #endif
#else
        #ifdef SURFACE        /* really neccessary ? */
        window(2,3,79,24);
        #endif
        v_scroll(0,2,79,23,1,V_SCROLL_DOWN);
#endif
        w_top--;w_bot--;
        fixline(w_top);
#ifdef DJ                       /* a.r. insline is not really well implemented */
        fixline(w_top+1);
#endif
}
text_scroll_up()
{
#ifndef EMXOS2                                          /* a.r. */
        gotoxy(1,1); delline();
#else
        v_scroll(0,2,79,23,1,V_SCROLL_UP);
#endif
        w_top++; w_bot++;
        fixline(w_bot);
}
scrdeleteline(int y)
{
#ifndef EMXOS2                                          /* a.r. */
        gotoxy(1, y - w_top + 1);
        delline();
        fixline(w_bot);
#else
        v_scroll( 0, y - w_top + 2, 79, 23, 1, V_SCROLL_UP );
        fixline(w_bot);
#endif
}
extern int noscreenio;
char *function_bar(void);
fner_clear()
{
        if (noscreenio) return;
        if (iserr==false) return;
        if (dont_clear) return;
        window(1,1,80,25);
        gotoxy(1,25);
        scr_grey();
        clreol();
        gotoxy(2,25);
        cputs(function_bar());
        scr_norm();
        iserr = false;
#if (defined DJ || defined EMXOS2)                      /* a.r. */
        window(2,3,79,24);
#else
        window(2,3,79,23);
#endif
}
fner(char *s)
{
        if (dont_clear) return;
        if (noscreenio) {
                printf("%s\n",s);
                return;
        }
        scr_savexy();
        iserr = true;
        window(1,1,80,25);
        gotoxy(1,25);
        scr_inv();
        clreol();
        gotoxy(2,25);
        cputs(s);
        scr_norm();
        scr_restorexy();
        scr_refresh();
}
int read_command(char *ans,char *ques)
{
        int rr;
        iserr = true;
        window(1,1,80,25);
        gotoxy(1,24);
        scr_inv();
        clreol();
        gotoxy(2,24);
        cputs(ques);
        rr = read_str(ans);
        gotoxy(1,24);
        scr_norm();
        clreol();
#if (defined DJ || defined EMXOS2)                      /* a.r. */
        window(2,3,79,24);
#else
        window(2,3,79,23);
#endif
        text_move(tfx,tfy);
        return rr;
}
int read_input(char *ans,char *ques)
{
        int rr;
        iserr = true;
        clreol();
        cputs(ques);
        rr = read_str(ans);
        #ifdef DJ                              /* a.r. */
        wprintf("\n\r        ");
        #else
        wprintf("\n");
        #endif
        return rr;
}

int read_str(char *s)
{
        int c,cx=0;
        char mbuff[80];
        *s = 0;
        for (;;) {
         c = text_inkey();
         switch (c) {
           case eescape: /* ESCAPE */
           case equit: /* control c */
                return true;
           case epageup:
                return epageup;
           case epagedown:
                return epagedown;
           case eleft: /* left */
                if (cx <= 0) break;
                cx--;
                scr_left(1);
                break;
           case eright: /* right */
                if (cx >= strlen(s)) break;
                cx++;
                scr_right(1);
                break;
           case eup: /* arrow up */
           case edown: /* arrow down */
          case ehelp: /* f1 help */
                break;
          case ereturn: /* carriage return */
                return false;
          case edelete: /* delete */
                if (strlen(s)==0) break;
                if (cx<1) break;
                ncpy(mbuff,s,cx-1);
                strcat(mbuff,s + cx);
                strcpy(s,mbuff);
                cx--;
                scr_left(1);
                cputs(s + cx);
                putch(' ');
                scr_left(strlen(s+cx)+1);
                break;
          case eshowerror:
          case edrawit:
                break;
          default: /* normal key */
                if (c<26  && c!=9) {fner("Key has no affect"); break;}
                if (c>200)  fner("Unimplemented command");
                else {
                        ncpy(mbuff,s,cx);
                        mbuff[cx] = c; mbuff[cx+1] = 0;
                        strcat(mbuff,s + cx);
                        strcpy(s,mbuff);
                        cputs(s + cx);
                        cx++;
                        scr_left(strlen(s+cx));
                }
                break;
           }
         }
}
normal_key(int c)
{
        static char lbuff[255];
        if (ngtxt+1==tfy) {
                text_up();
                text_eol();
                text_return();
        }
        ncpy(lbuff,line(tfy),tfx-1);
        lbuff[tfx-1] = c; lbuff[tfx]=0;
        strcat(lbuff,line(tfy)+tfx-1);
        tfx++;
        lineset(tfy,lbuff);
}
text_showerror()
{
        int i,n;

       #ifdef EMXOS2                            /* a.r. */
        FILE *fptr;
        int j;
        char buffer[256];

        g_get_type(devtype);
        if (strstr(devtype, "HARDCOPY") == NULL)
               {
                clrscr();
                fptr = fopen("GLEOS2.ERR","r");
                if (fptr == NULL) 
                       {
                        fner("There were no errors. Press any key to continue...");
                        text_inkey();
                        return;
                       }
                else
                         for (j = 0;!feof(fptr); j++)
                               {
                                if (fgets(buffer,80,fptr)!=NULL)
                                       {
                                        v_gotoxy(0,j);
                                        v_puts(buffer);
                                       }
                               }
                fclose(fptr);
               }
                fner("Press any key to continue...");
                text_inkey();
                return;
       #endif                   /* EMXOS2 */
        if (netxt==0) {
                fner("There were no errors, press return");
                text_inkey();
                return;
        }
        clrscr();
        n = netxt;
        if (n>20) n = 17;
        for (i=1;i<=n;i++) {
                gotoxy(3,i);
                cputs( (*etxt)[i] );
        }
        gotoxy(1,20); cputs("Press any key to continue");
        text_inkey();
}
#ifndef unix
void wprintf(va_list arg_list, ...)
/* Prints to the window */
{
        va_list arg_ptr;
        char *format;
        char output[200];

        va_start(arg_ptr, arg_list);
        format = arg_list;
        vsprintf(output, format, arg_ptr);
#ifdef __TURBOC__
        printf(output);
#else
        cputs(output);
#endif
}
#endif
