#include "all.h"
#include "color.h"
#include "edt.h"

#ifdef __TURBOC__
        #define DASHCHAR 249
        #include "bios.h"
        #include "conio.h"
        #include "dir.h"
#elif DJ                                        /* a.r. */
        #define clrscr ScreenClear
        #include <gppconio.h>
        #include <dir.h>
        #define DASHCHAR 249
#elif EMXOS2                                    /* a.r. */
        #define INCL_DOS
        #include <os2.h>
        #include <conio.h>
        #include <sys/types.h>
        #include <sys/dir.h>
        #define DASHCHAR 249
        #define WHITE 15
        #define BLACK 0
#else
        #define DASHCHAR '.'
        #include "vaxconio.h"
#endif

#define true (!false)
#define false 0
#define BEGINDEF extern
/* #include "begin.h" */
#define BCOLOR BLUE
#define FCOLOR MAGENTA
#define HBCOLOR h_bcolor
#define HVCOLOR h_fcolor
#define VCOLOR WHITE

int h_bcolor;
int h_fcolor;
int getsize(void);
char *tabtospace(char *s);
int printdash(int i);
char *gledir(char *s);
char *gletopdir(char *s);
int scr_menuval(void);
int scr_menubg(void);
int scr_menuhi(void);
int scr_grey(void);
int gle_redraw(void);
int text_showerror(void);
int text_save(void);
char *strfile(char *s);

int vdelete(int i);
int vinsert(int y, char *s);
int m_ifsend(char *s);
int m_sendline(void);
int minit_extras(void);
int minit_extras(void);
int initmenu(void);
int mystrlen(char *s);
int pick_file(char *d, char *w);
int ncpy(char *d, char *s, int n);
int setvstr(char **d, char *s);
int text_inkey(void);

struct menu_struct { int x; int y; char *title; int width; int typ; int typ2;
        char *val; char *help; };
typedef struct menu_struct menutype;
struct pmenu_struct {int ci; menutype *menu; };
typedef struct pmenu_struct pmenutype;
pmenutype pmenu[17];
int setmenu(menutype *m,int x, int y, int typ, int typ2, int width, char *title
        , char *val, char *help);
int do_menu(pmenutype *p);
int token_space(void);
int extractmenu(void);
int add_unrecognized(char *s);
int fillinmenu(int nbegin);
int nunrec;

#define  PTXT 0
enum {MEND,MTEXT,MFILE,MTOGON,MTOGOFF,MSUB,MRETURN,MNULL};
enum {SNORM,SROL,SNEXTS,SNEXT,SSTR,STOG,SS,SSIZE,SNOBOX,SAMOVE,SSOFF,SSNULL};
int refresh_menu(struct menu_struct *m);
int menu_hilight(struct menu_struct *m);
int menu_norm(struct menu_struct *m);

/* menu's
        topmenu
                title,xtitle,ytitle min max dist on off, ticks dticks
                (2) let d = exp
                Data files
                Dn marker ,color, lwidth, lstyle, err,
        xnamesmenu
        ynamesmenu
        fillmenu
        barmenu
        axismenu's
*/
read_default(char *result, char *ques, char *dflt)
{
        char s[200];
        int r;
        strcpy(s,ques); strcat(s," ["); strcat(s,dflt); strcat(s,"] ");
/*        r = read_input(result,s);*/
        if (strlen(result)==0) strcpy(result,dflt);
        return r;
}
extern int changed;
addline(char *s)
{
        changed = true;
}
char *mark_names[] = {
        "dot", "square", "fcircle", "club", "diamond", "triangle", "snake"
        ,"otimes", "odot", ""};

int init_menucolor(void);
int m_gstart,m_gend;
/*

        Getkey/command
                arrowkeys normal
                left and right arrow if editing
                delete
                insert normal character
                enter, change to new menu
                escape exit.
                F1, help key
*/
char mbuff[255];

extern int iserr;
int hcx,cx,hcy;        /* HIlighted current x,y */
do_menu(pmenutype *ppmenu)
{
        menutype *cm,*cmi,*si=NULL,*mi;
        int citem,emode=false;
        int c;
        cm = ppmenu->menu;
        citem = ppmenu->ci;
        cmi = cm+citem;
        refresh_menu(cm);
        menu_hilight(cmi);
        for (;;) {
         c = text_inkey();
         if (iserr) {fner_clear(); window(1,1,80,24);}
         switch (c) {
           case eescape: /* ESCAPE */
           case equit: /* control c */
                return true;
           case eleft: /* left */
                if (emode) {
                        if (cx>0) cx--;
                        gotoxy(hcx+cx,hcy);
                } else {
                        for (si=NULL,mi=cm;mi->typ!=0;mi++) {
                                if (mi->y==cmi->y && mi->x < cmi->x)
                                if (si!=NULL) {
                                        if (mi->x > si->x)
                                                si = mi;
                                } else si = mi;
                        }
                }
                break;
           case eright: /* right */
                if (emode) {
                        if (cx < strlen(cmi->val)) cx++;
                        gotoxy(hcx+cx,hcy);
                } else {
                        for (si=NULL,mi=cm;mi->typ!=0;mi++) {
                                if (mi->y==cmi->y && mi->x > cmi->x)
                                if (si!=NULL) {
                                        if (mi->x < si->x)
                                                si = mi;
                                } else si = mi;

                        }
                }
                break;
           case eup: /* arrow up */
                emode = false;
                for (si=NULL,mi=cm;mi->typ!=0;mi++) {
                        if (mi->typ<MNULL) {
                         if (si!=NULL) if (mi->y==si->y)
                           if (abs(mi->x - cmi->x) <  abs(si->x - cmi->x))
                                si = mi;
                         if (mi->y < cmi->y) if (si!=NULL) {
                           if (mi->y > si->y) si = mi;
                         } else          si = mi;
                        }
                }
                break;
           case edown: /* arrow down */
                emode = false;
                for (si=NULL,mi=cm;mi->typ!=0;mi++) {
                        if (mi->typ<MNULL) {
                         if (si!=NULL) if (mi->y==si->y)
                           if (abs(mi->x - cmi->x) <  abs(si->x - cmi->x))
                                si = mi;
                         if (mi->y > cmi->y) if (si!=NULL) {
                           if (mi->y < si->y) si = mi;
                         } else  si = mi;
                        }
                }
                break;
          case ehelp: /* f1 help */
                do_help(cmi->help);
                refresh_menu(cm);
                menu_hilight(cmi);
                break;
          case ereturn: /* carriage return */
                if (emode==true && cmi->typ==MFILE) {
                        emode = false;
                        break;
                }
                emode = false;
doreturn:;
                switch (cmi->typ) {
                  case MTEXT:
/*                        if (emode) emode = false; else emode = true; */
                        break;
                  case MTOGON:
                        cmi->typ = MTOGOFF;
                        menu_hilight(cmi);
                        break;
                  case MTOGOFF:
                        cmi->typ = MTOGON;
                        menu_hilight(cmi);
                        break;
                  case MRETURN:
                        goto exit_menu;
                  case MFILE:
                        if (mystrlen(cmi->val)==0) cmi->val = myallocz(20);
                        pick_file(cmi->val,"*.dat");
                        refresh_menu(cm);
                        menu_hilight(cmi);
                        break;
                  case MSUB: /* SUB MENU */
                        if (cmi->typ2>99) do_menu(&pmenu[cmi->typ2 - 100]);
                        refresh_menu(cm);
                        menu_hilight(cmi);
                }

                for (si=NULL,mi=cm;mi->typ!=0;mi++) {
                        if (mi->y==cmi->y && mi->x > cmi->x)
                        if (si!=NULL) {
                                if (mi->x < si->x)
                                        si = mi;
                        } else si = mi;
                }

                break;
          case edelete: /* delete */
                emode = true;
                if (cmi->val==NULL) break;
                if (strlen(cmi->val)==0) break;
                if (cx<1) break;
                ncpy(mbuff,cmi->val,cx-1);
                strcat(mbuff,cmi->val + cx);
                setvstr(&cmi->val,mbuff);
                cx--;
                gotoxy(hcx+cx,hcy);
                cputs(cmi->val + cx);
                putch(DASHCHAR);
                gotoxy(hcx+cx,hcy);
                break;
          case edrawit:
                break;
          case eshowerror:
                break;
          case esave: /* save file */
                break;
          default: /* normal key */
                if (c<26  && c!=9) {fner("Key has no affect"); break;}
                if (c>200)  fner("Unimplemented command");
                else {
/*         if (cmi->typ!=MTEXT  && cmi->typ!=MFILE) goto doreturn; */
                        emode = true;
                        if (cmi->val==NULL) setvstr(&cmi->val,"");
                        ncpy(mbuff,cmi->val,cx);
                        mbuff[cx] = c; mbuff[cx+1] = 0;
                        strcat(mbuff,cmi->val + cx);
                        setvstr(&cmi->val,mbuff);
                        gotoxy(hcx+cx,hcy);
                        cputs(cmi->val + cx);
                        cx++;
                        gotoxy(hcx+cx,hcy);
                }
                break;
         }
         if (si!=NULL) {
                menu_norm(cmi);
                cmi = si;
                menu_hilight(cmi);
                si = NULL;
         }
        }
exit_menu:;
        /* save current point */
        { int i;
                for (i=0,mi=cm;mi->typ!=0;mi++,i++) {
                  if (mi==cmi) ppmenu->ci = i;
                }
        }
        return false; /* normal exit */
}
setvstr(char **d, char *s)
{
        if ((*d) != 0) myfree(*d);
        *d = sdup(s);
}
int mystrlen(char *s)
{
        if (s==NULL) return 0;
        else return strlen(s);
}
menu_hilight(struct menu_struct *mm)
{
        int i,j;
        struct menu_struct *m=mm;
        scr_menuhi();
        hcx = m->x + mystrlen(m->title);
        hcy = m->y;
        gotoxy(hcx,hcy);
        if (m->typ==MTOGON || m->typ==MTOGOFF) {
                if (m->val==NULL) m->val = myallocz(4);
                if (m->typ==MTOGON) strcpy(m->val,"ON ");
                if (m->typ==MTOGOFF) strcpy(m->val,"OFF");
        }
        if (m->val==NULL) setvstr(&m->val,"");
        cputs(m->val);
        j = m->width - mystrlen(m->val);
        printdash(j);
        cx = mystrlen(m->val);
        gotoxy(hcx+cx,hcy);
}
printdash(int j)
{
        int i;
        for (i=0;i<j;i++) mbuff[i] = DASHCHAR;
        mbuff[j] = 0;
        if (j>0) cputs(mbuff);
}
menu_norm(struct menu_struct *mm)
{
        int i,j;
        struct menu_struct *m=mm;
        gotoxy(m->x + mystrlen(m->title),m->y);
        if (m->typ==MTOGON  || m->typ==MTOGOFF) {
                if (m->val==NULL) m->val = myallocz(4);
                if (m->typ==MTOGON) strcpy(m->val,"ON ");
                if (m->typ==MTOGOFF) strcpy(m->val,"OFF");
        }
        if (m->val != NULL) {
                scr_menuval();
                if (m->width>0) cputs(m->val);
                scr_menubg();
        }
        j = m->width - mystrlen(m->val);
        printdash(j);
}
refresh_menu(struct menu_struct *mm)
{
        int i;
        struct menu_struct *m=mm;
        window(1,1,80,24);
        scr_menubg();
        clrscr();
        for (;m->typ!=0;m++) {
                if (m->title != NULL) if (strlen(m->title)>0) {
                        gotoxy(m->x,m->y);
                        cputs(m->title);
                }
                menu_norm(m);
        }
}
do_help(char *k1)
{
  char kbuff[80];
  strcpy(kbuff,k1);
        do_help2(kbuff,"");
}
do_help2(char *k1, char *k2)
{
        FILE *hfile;
        int i,yy;
        char hbuff[90];
        char *hfilename="surface.hlp";
        char fk1[20],fk2[20],*os,*si;
        char savek1[40],subtopic[40];


help_again:;
        window(1,1,80,24);
        strcpy(savek1,k1);
        scr_menuval();
        clrscr();
        if (strcmp(k2," ")==0) strcpy(k2,"");
        gotoxy(1,1); wprintf("SURFACE help on topic {%s},  sub topic {%s}",k1,k2);
        scr_menubg();
        hfile = fopen(gletopdir(hfilename),"r");
        if (hfile==NULL) perror("Unable to open surface.hlp ");
        for (;!feof(hfile);) {
                if (fgets(hbuff,90,hfile)!=NULL) {
                        if (hbuff[0]=='3') {
                                strtok(hbuff," \n");
                                strcpy(fk1,strtok(NULL," \n"));
                                if (strcmp(fk1,k1)==0 && strlen(k2)==0)
                                        goto help_type;
                        }
                        if (hbuff[0]=='4') {
                                strtok(hbuff," \n");
                                strcpy(fk2,strtok(NULL," \n"));
                                if (strlen(k2)>0)
                                if (strcmp(fk1,k1)==0 &&
                                        strcmp(fk2,k2)==0) goto help_type;
                        }
                }
        }
        fclose(hfile);
        scr_menuval();
        gotoxy(1,9);
        wprintf("help text not found sorry ??? \n");
        text_inkey();
        return;
help_type:;
        yy = 3;
        for (;!feof(hfile);) {
                if (fgets(hbuff,90,hfile)!=NULL) {
                        if (isdigit(hbuff[0])) {
                                goto end_help;
                        }
                        gotoxy(1,yy++); cputs(tabtospace(hbuff));
                }
                if (yy==22) {
                        scr_menuval();
                        gotoxy(2,24); wprintf("Press any key for next screen of help");
                        text_inkey();  clrscr();
                        gotoxy(1,1); wprintf("Graph help on topic {%s},  sub topic {%s}",k1,k2);
                        scr_menubg();  yy = 3;
                }
        }
end_help:;
        scr_menuval();
        gotoxy(1,yy+1);
        read_command(subtopic,"Subtopic [return to continue] ");
        strupr(subtopic);
        if (strlen(subtopic)!=0) {
                fclose(hfile);
               strcpy(k1,savek1);
                k2 = subtopic;
                goto help_again;
        }
        fclose(hfile);
}
add_unrecognized(char *s)
{
        if (nunrec>6) return;
}
int vunquote(char **s);
vunquote(char **ss)
{
        char *s = *ss;
        if (*s=='\"') {
                s[strlen(s)-1] = 0;
                *ss = sdup(s+1);
                myfree(s);
        }
}

int initmenudone;
menutype *m_pnt[20];
menutype *m_end[20];
char *m_val[20];
char m_tog[50];
initmenu()
{
        menutype *mi;
        char *s,kw1[80],kw2[80];
        int i,j,nt=0,k,z,ct,used;
        static int nv;

        if (!initmenudone) {
          initmenudone = true;
          for (z=0;z<=10;z++) {
            for (mi=pmenu[z].menu; mi->typ!=0; mi++) {
                if (mi->typ==MTOGON || mi->typ==MTOGOFF) {
                        m_tog[nt++] = mi->typ;
                }
                if (mi->val!=NULL) {
                        m_val[nv] = sdup(mi->val);
                        mi->val = sdup(mi->val);
                        m_pnt[nv++] = mi;
                }
            }
          }
        } else {
          for (z=0;z<=10;z++) {
            for (mi=pmenu[z].menu; mi->typ!=0; mi++) {
                if (mi->typ==MTOGON || mi->typ==MTOGOFF) {
                        mi->typ = m_tog[nt++];
                } else {
                        if (mi->val!=0) {
                                myfree(mi->val);
                        }
                        mi->val = 0;
                }
            }
          }
          for (z=0;z<nv;z++) {
                mi = m_pnt[z];
                mi->val = sdup(m_val[z]);
          }
        }
}

char msend[200];
#define mss msend+strlen(msend)
char cs[80]="xyz";
int gstartend;
/* char msend[200]; */
m_sendline()
{
        msend[0] = 0;
        strcpy(cs,"xyz");
}
m_ifsend(char *s)
{
        if (strcmp(s,cs)!=0) {
          m_sendline();
          sprintf(msend,"\t%s ",s);
          strcpy(cs,s);
        }
}
int g_get_usersize(double *x, double *y);
setmenu(menutype *m,int x, int y, int typ, int typ2, int width, char *title
, char *val, char *help)
{
        m->x = x; m->y = y; m->typ = typ; m->typ2 = typ2; m->width = width;
        m->title = sdup(title);
        if (val!=0) m->val = sdup(val);
        m->help = sdup(help);
}
init_menucolor()
{
                h_bcolor = WHITE; h_fcolor = BLACK;
}
int pick_file(char *result, char *wld)
{
        pmenutype ask;
        char wild[80];
        char buff2[80];
        char *f[80];
        char *swap;
        menutype *m,*mi,*mwild;
#ifndef EMXOS2                                  /* a.r. */
        struct ffblk ffblk;
#else
        HDIR            hdir;
        FILEFINDBUF3    FFbufr;
        unsigned long   SearchCnt;
#endif
        int done,i,x,y,nf,rval,adddir=false;

        strcpy(wild,wld);
        ask.ci = 0;
pick_again:;
        x=0; y=0; nf=0;
        init_menucolor();
#ifndef EMXOS2                                  /* a.r. */
        done = findfirst(wild,&ffblk,0);
        for (nf=0;nf<70 && !done;nf++) {
                f[nf] = sdup(ffblk.ff_name);
                done = findnext(&ffblk);
        }
#else
        SearchCnt = 1; 
        hdir = HDIR_SYSTEM; 
        done = DosFindFirst(    wild,
                                &hdir,
                                0,
                                &FFbufr,
                                sizeof(FFbufr),
                                &SearchCnt,
                                FIL_STANDARD);
        for (nf=0;nf<70 && !done;nf++) {
                f[nf] = sdup(FFbufr.achName);
                done = DosFindNext( hdir,
                                    &FFbufr,
                                    sizeof(FFbufr),
                                    &SearchCnt);
                }
#endif
sortagain:;
        swap = NULL;
        for (i=0;i<(nf-1);i++) {
                if (strcmp(f[i],f[i+1])>0) {
                        swap = f[i]; f[i] = f[i+1]; f[i+1] = swap;
                }
        }
        if (swap != NULL) goto sortagain;

        m = myallocz((3+nf)*sizeof(*m));
        ask.menu = m;
        ask.ci = 0;
        if (nf==0) ask.ci = 1;
        if (m==0) wprintf("memory allocation error");
        for (mi=m,i=0;i<nf;i++,mi++) {
                setmenu(mi,x*20+1,y+5,MRETURN,0,18,"",f[i],"");
                x++;
                if (x==4) {x=0; y++; }
        }
        setmenu(mi,5,1,MNULL,0,0,"Use arrow keys to select file then press return","","");
        mi++;
        setmenu(mi,5,3,MRETURN,0,30,"Disk/Dir Specification ",wild,"");
        mwild = mi;
        mi++; mi->typ = 0;
        rval = do_menu(&ask);
        strcpy(result,((ask.menu)[ask.ci]).val);
        for (i=0;i<nf;i++) myfree(f[i]);
        myfree(m);

        if (strcmp(wild,mwild->val)!=0) {
                strcpy(wild,mwild->val);
                if (strstr(wild,"*")==NULL) {
                        if (wild[strlen(wild)-1] == '\\')
                                strcat(wild,"*.sur");
                        else
                                strcat(wild,"\\*.sur");
                }
                adddir = true;
                goto pick_again;
        }

        if (adddir) {
                *(strfile(wild)) = 0;
#if (defined __TURBOC__ || defined DJ)
                if (strstr(wild,":")!=NULL) {
                        setdisk(toupper(*wild)-'A');
                }
                strcpy(buff2,wild+2); strcpy(wild,buff2);
#endif
#ifdef EMXOS2                                                   /* a.r. */
                if (strstr(wild,":")!=NULL) {
                        DosSetDefaultDisk(toupper(*wild)-'A' + 1);
                }
                if (_chdir2(wild)!=0) {perror("Cannot change dir"); delay(3000);}
#else
                if (chdir(wild)!=0) {perror("Cannot change dir"); delay(3000);}
#endif
        }

/*        if (adddir) {
                *(strfile(wild)+1) = 0;
                strcpy(result,wild);
                strcat(result,((ask.menu)[ask.ci]).val);
        }
*/
        return rval;
}
char *strfile(char *s)
{
        char *e;
        e = s;
        for (;*s!=0;s++) {
                if (*s==']'  ||  *s=='\\' || *s=='/' || *s==':') e = s;
        }
        return e;
}
