/*
  input.c - some input- and output-routines
  Written by Stefan Pfeiffer, DL1ELY, 940405
  Last Modification: 960105
  (C) 1994 by Stefan Pfeiffer, DL1ELY
*/

#include <conio.h>
#include <string.h>
#include <mem.h>
#include <dos.h>
#include <dir.h>
#include <alloc.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include "dvideo.h"
#include "secmem.h"
#include "input.h"
#include "egavga.h"

uchar glob_y;
uchar glob_col;
unsigned long glob_max;
uchar glob_akt_x;



   
void paint_but(uchar x, uchar y, pchar text, uchar col, uchar backcol)
{
   uchar width;
   uchar shadowcol;
  
   shadowcol = (backcol&0xF0) + BLACK;
  
   if(strlen(text)<8)
   {
      width = 9-(strlen(text)%2);
      dfill(x,y,x+width,y,' ',col);
      dprint(x+((width-strlen(text))>>1)+1,y,col,text);
   }
   else
   {
      width = strlen(text)+1;
      dfill(x,y,x+width,y,' ',col);
      dprint(x+((width-strlen(text))>>1)+1,y,col,text);
   };
    
   dfill(x+1,y+1,x+width+1,y+1,223,shadowcol);
   dprint(x+width+1,y,shadowcol,"\334");
};  

  
void ok_box(pchar title, pchar text)
{
   void *save;
   uchar width;
   uchar xpos;
   uchar mid;

   mid = (lastrow+1)>>1;
   width = strlen(text) < 36 ? 40 : strlen(text)+4;
   if(strlen(title) > width-4) width = strlen(title+4);
   xpos = mid-(width>>1);
  
   save = make_win(xpos,5,xpos+width,12,menucol);
   dprint(mid-(strlen(title)>>1),6,menucol,title);
   dprint(mid-(strlen(text)>>1),8,menucol,text);
   paint_but(mid-3,10,"OK",activebuttoncol,menucol);
  
   for(;getch()!=13;);
  
   drestore(save);
   sec_free(save);
}

uchar ok_abort_box(pchar title, pchar text)
{
   void *save;
   uchar width;
   uchar xpos;
   uchar selection;
   uchar mid;

   mid = (lastrow+1)>>1;
   width = strlen(text) < 36 ? 40 : strlen(text)+4;
   if(strlen(title) > width-4) width = strlen(title)+4;
   xpos = mid-(width>>1);
  
   save = make_win(xpos,5,xpos+width,12,menucol);

   dprint(mid-(strlen(title)>>1),6,menucol,title);
   dprint(mid-(strlen(text)>>1),8,menucol,text);
   paint_but(mid-12,10,"OK",activebuttoncol,menucol);
   paint_but(mid+1,10,"  Abort  ",passivebuttoncol,menucol);
  
   selection = 1;
   for(;;)
   {
      switch(getch())
      {
         case 0:
            switch(getch())
            {
               case 75:     // Cursor left
                  selection = 1;
                  break;
               case 77:     // Cursor right
                  selection = 2;
                  break;
            }
            if(selection == 1)
            {
               paint_but(mid-12,10,"OK",activebuttoncol,menucol);
               paint_but(mid+1,10,"  Abort  ",passivebuttoncol,menucol);
            }
            else
            {
               paint_but(mid-12,10,"OK",passivebuttoncol,menucol);
               paint_but(mid+1,10,"  Abort  ",activebuttoncol,menucol);
            };
            break;
         case 32:
         case 9:
            if(selection == 1)
            {
               selection = 2;
               paint_but(mid-12,10,"OK",passivebuttoncol,menucol);
               paint_but(mid+1,10,"  Abort  ",activebuttoncol,menucol);
            }
            else
            {
               selection = 1;
               paint_but(mid-12,10,"OK",activebuttoncol,menucol);
               paint_but(mid+1,10,"  Abort  ",passivebuttoncol,menucol);
            }
            break;
         case 13:
            drestore(save);
            sec_free(save);
            return(selection == 1);
         case 'O':
         case 'o':
            drestore(save);
            sec_free(save);
            return(1);
         case 27:
         case 'A':
         case 'a':
            drestore(save);
            sec_free(save);
            return(0);
      }
   }
}


uchar yes_no_box(pchar title, pchar text)
{
   void *save;
   uchar width;
   uchar xpos;
   uchar selection;
   uchar mid;

   mid = (lastrow+1)>>1;
   width = strlen(text) < 36 ? 40 : strlen(text)+4;
   if(strlen(title) > width-4) width = strlen(title)+4;
   xpos = mid-(width>>1);
  
   save = make_win(xpos,5,xpos+width,12,menucol);

   dprint(mid-(strlen(title)>>1),6,menucol,title);
   dprint(mid-(strlen(text)>>1),8,menucol,text);
   paint_but(mid-12,10,"Yes",activebuttoncol,menucol);
   paint_but(mid+1,10," No ",passivebuttoncol,menucol);
   selection = 1;
   for(;;)
   {
      switch(getch())
      {
         case 0:
            switch(getch())
            {
               case 75:     // Cursor left
                  selection = 1;
                  break;
               case 77:     // Cursor right
                  selection = 2;
                  break;
            }
            if(selection == 1)
            {
               paint_but(mid-12,10,"Yes",activebuttoncol,menucol);
               paint_but(mid+1,10," No ",passivebuttoncol,menucol);
            }
            else
            {
               paint_but(mid-12,10,"Yes",passivebuttoncol,menucol);
               paint_but(mid+1,10," No ",activebuttoncol,menucol);
            }
            break;
         case 32:
         case 9:
            if(selection == 1)
            {
               selection = 2;
               paint_but(mid-12,10,"Yes",passivebuttoncol,menucol);
               paint_but(mid+1,10," No ",activebuttoncol,menucol);
            }
            else
            {
               selection = 1;
               paint_but(mid-12,10,"Yes",activebuttoncol,menucol);
               paint_but(mid+1,10," No ",passivebuttoncol,menucol);
            }
            break;
         case 13:
            drestore(save);
            sec_free(save);
            return(selection == 1);
         case 'J':
         case 'j':
         case 'Y':
         case 'y':
            drestore(save);
            sec_free(save);
            return(1);
         case 27:
         case 'N':
         case 'n':
            drestore(save);
            sec_free(save);
            return(0);
      }
   }
}


int input_string(uchar x, uchar y, uchar maxlen, uchar visible, uchar mode, uchar col, pchar s)
{
   uchar slen = 0, cpos = 0, spos = 0;
   uchar insert;
   uchar do_tab, auto_tab;
   uchar up;
   uchar convert;
   uchar digits;
   uchar color;
   uchar ch;
   uchar def;
   uchar hlp[80];
  
   if(!visible) visible = maxlen;
   insert = mode & INSERT;
   do_tab = mode & DO_TAB;
   auto_tab = mode & AUTO_JUMP;
   up = mode & UPCASE;
   convert = mode & CALL_CONVERT;
   digits = mode & DIGITS_ONLY;
   color = ((col&0x0F)<<4) + (col>>4);
   def = 1;
  
   if(insert) def_cursor(6,7);
   else def_cursor(0,7);
  
   if(*s)
   {
      slen = strlen(s);
      if(slen > visible) spos = slen-visible;
      cpos = slen-spos;
   }
  
   do
   {
      dfill(x,y,x+visible-1,y,' ',col);
      memmove(hlp,(s+spos),visible);
      if(slen > visible) hlp[visible] = 0;
      else hlp[slen] = 0;
      dprint(x,y,color,hlp);

      if(spos) dprint(x,y,color,"\x11");
      if(slen > (spos+visible)) dprint(x+visible,y,color,"\x10");
 
      my_gotoxy(x+cpos,y);
      ch = getch();
      if(!ch)
      {
         ch = getch();
         switch(ch)
         {
            case 77:      // Cursor right
               if(cpos < slen) cpos++;
               if(cpos > visible)
               {
                  cpos--;
                  spos++;
               };
               color = col;
               def = 0;
               break;
            case 75:      // Cursor left
               if(spos)
               {
                  if(cpos) cpos--;
                  else spos--;
               }
               else if(cpos) cpos--;
               color = col;
               def = 0;
               break;
            case 15:
               color = col;
               def = 0;
               if(do_tab)
               {
                  memmove(hlp,(s+spos),visible);
                  if(visible>slen) hlp[visible] = 0;
                  else hlp[slen] = 0;
                  dprint(x,y,color,hlp);
                  return(BACKTAB);
               };
               break;
            case 82:
               insert^=1;
               if(insert) def_cursor(6,7);
               else def_cursor(0,7);
               color = col;
               def = 0;
               break;
            case 83:
               if(cpos < slen)
               {
                  memmove((pchar)s+cpos,(pchar)s+cpos+1,slen-cpos+1);
                  slen--;
               }
               color = col;
               def = 0;
               break;
         }
      }
      else
      {
         switch(ch)
         {
            case 9:
               color = col;
               def = 0;
               if(do_tab)
               {
                  memmove(hlp,(s+spos),visible);
                  if(slen > visible) hlp[visible] = 0;
                  else hlp[slen] = 0;
                  dprint(x,y,color,hlp);
                  return(TAB);
               }
               break;
            case 8:
               if((cpos+spos) > 0)
               {
                  memmove((pchar)s+cpos+spos-1,(pchar)s+cpos+spos,slen-cpos-spos+1);
                  slen--;
                  if(cpos>3) cpos--;
                  else if(spos) spos--;
                       else cpos--;
               }
               else
               {
                  sound(100);
                  delay(50);
                  nosound();
               }
               color = col;
               def = 0;
               break;
            case 13:
            case 27:
               break;


            case '-':
            case 225:
               if(convert) ch = '/';
        
            default:
               if(up) ch = toupper(ch);
               if(digits&&(!isdigit(ch))) break;
               if(def)
               {
                  slen = 0;
                  spos = 0;
                  cpos = 0;
                  def = 0;
                  color = col;
               };
          
               if(slen < maxlen || !insert)
               {
                  if(slen == maxlen && (cpos+spos) == slen)
                  {
                     if(auto_tab)
                     {
                        memmove(hlp,(s+spos),visible);
                        if(slen > visible) hlp[visible] = 0;
                        else hlp[slen] = 0;
                        dprint(x,y,color,hlp);
                        return(TAB);
                     }
                     else
                     {
                        sound(100);
                        delay(50);
                        nosound();
                     };
                  }
                  else
                  {
                     if(insert && (cpos+spos) < slen)
                     {
                        memmove((pchar)s+cpos+spos+1,(pchar)s+cpos+spos,slen-cpos-spos+1);
                        slen++;
                     }
                     *(s+cpos+spos) = ch;
                     cpos++;
                     if(cpos > visible)
                     {
                        cpos--;
                        spos++;
                     };
                     if(slen < (cpos+spos))
                     {
                        slen++;
                        *(s+slen) = 0;
                     }
                  }
              }
              else
              {
                 if(auto_tab)
                 {
                    memmove(hlp,(s+spos),visible);
                    if(slen > visible) hlp[visible] = 0;
                    else hlp[slen] = 0;
                    dprint(x,y,color,hlp);
                    return(TAB);
                 }
                 else
                 {
                    sound(100);
                    delay(50);
                    nosound();
                 };
              }
              break;
         }
      }
   } while(ch != 13 && ch != 27);
  
   strcpy(hlp,s);
   hlp[visible] = 0;
   dprint(x,y,col,hlp);
   return(ch == 13);
}

void far *make_win(uchar x1, uchar y1, uchar x2, uchar y2, uchar col)
{
   void *save;

   uchar x;
   unsigned far *vptr;
   uchar attr;


   save = dsave(x1,y1,x2+2,y2+1);
   dfill(x1,y1,x2,y2,' ',col);
   dframe(x1,y1,x2,y2,col);
 
   for(x=y1+1;x<=y2;x++)
   {
      vptr = (unsigned far *)MK_FP(startseg,((x*(lastrow+1))+x2+1)*2);
      attr = *vptr >> 8;
      if(attr & 0x80) attr = attr&0x7F;
      else attr = attr&0x0F;
      if(attr & 0x08) attr = attr&0xF7;
      else attr = attr&0xF0;
      *vptr = (*vptr & 0xFF) + (attr<<8);

      vptr++;
      attr = *vptr >> 8;
      if(attr & 0x80) attr = attr&0x7F;
      else attr = attr&0x0F;
      if(attr & 0x08) attr = attr&0xF7;
      else attr = attr&0xF0;
      *vptr = (*vptr & 0xFF) + (attr<<8);
   };

   vptr = (unsigned far *)MK_FP(startseg,(((y2+1)*(lastrow+1))+x1+2)*2);
   for(x=x1+2;x<=x2+2;x++)
   {
      attr = *vptr >> 8;
      if(attr & 0x80) attr = attr&0x7F;
      else attr = attr&0x0F;
      if(attr & 0x08) attr = attr&0xF7;
      else attr = attr&0xF0;
      *vptr = (*vptr & 0xFF) + (attr<<8);
      vptr++;
   };

   return(save);
}


void init_bar(uchar y, uchar col, unsigned long max)
{
    glob_y = y;
    glob_col = col;
    glob_max = max;
    glob_akt_x = 0;

    dfill(15,y,65,y,177,col);
    dfill(16,y-2,64,y-2,196,col);
    dprint(15,y-2,col,"\332");
    dprint(65,y-2,col,"\277");
    dprint(40,y-2,col,"\302");
    dprint(27,y-2,col,"\302");
    dprint(52,y-2,col,"\302");

    dprint(15,y-1,col,"0%");
    dprint(26,y-1,col,"25%");
    dprint(39,y-1,col,"50%");
    dprint(51,y-1,col,"75%");
    dprint(62,y-1,col,"100%");
};


void paint_bar(unsigned long value)
{
   uchar xpos;
   double ratio;

   ratio = (double)value/glob_max;
   xpos = (unsigned char)(ratio*50.0);
   if(xpos > glob_akt_x)
   {
      dfill(15+glob_akt_x,glob_y,15+xpos,glob_y,219,glob_col);
      glob_akt_x =  xpos;
   };
}


int far filesortfunc(const void *a, const void *b)
{
   struct fentry *af;
   struct fentry *bf;

   af = (struct fentry *)a;
   bf = (struct fentry *)b;

   if(af->dir!=bf->dir)
   {
      if(af->dir) return -1;
      else return(1);
   }
   else
      return strcmp(af->name, bf->name);
};


unsigned fill_files(struct fentry *fe, pchar mask)
{
   struct ffblk blk;
   unsigned done;
   unsigned cnt = 0;
   uchar drive[3];
   uchar path[128];
   uchar name[9];
   uchar ext[5];
   uchar s[128];

   fnsplit(mask,drive,path,name,ext);
   sprintf(s,"%s%s*.*",drive,path);

   done = findfirst(s,&blk,0x10);
   while(!done)
   {
      if(strcmp(blk.ff_name,".") && (blk.ff_attrib & 0x10))
      {
         strcpy(fe[cnt].name,blk.ff_name);
         fe[cnt].dir = 1;
         cnt++;
      };
      done = findnext(&blk);
   };

   done = findfirst(mask,&blk,0);
   while(!done)
   {
      strcpy(fe[cnt].name,blk.ff_name);
      fe[cnt].dir = 0;
      cnt++;
      done = findnext(&blk);
   };

   qsort(fe,cnt,sizeof(struct fentry),filesortfunc);

   return cnt;
};

#define FS_Y   5
#define FS_CNT 8
#define MAX_FILE 255

char file_select(pchar mask, uchar col1, uchar col2)
{
   struct fentry *files;
   unsigned vis;
   unsigned sel;
   void *save;
   unsigned i;
   unsigned cnt;
   uchar ch;
   uchar drive[3];
   uchar *cp;
   uchar path[128];
   uchar name[9];
   uchar ext[5];
   BOOL ende = 0;
   uchar full[128];

   save = make_win(49,FS_Y,71,FS_Y+FS_CNT+2,col1);

   files = sec_alloc((sizeof(struct fentry)*MAX_FILE)+15);

   _fullpath(full,mask,128);

   do
   {
      memset(files,0,sizeof(struct fentry)*MAX_FILE);
      cnt = fill_files(files,full);
 
      if(!cnt)
      {
         sec_free(files);
         drestore(save);
         sec_free(save);
         return(0);
      };

      dfill(50,FS_Y+1,70,FS_Y+FS_CNT+1,' ',col1);
      for(i = 0;i < cnt && i <= FS_CNT;i++)
         if(files[i].dir) dprintf(51,i+FS_Y+1,col1,"%s\\",files[i].name);
      else dprint(51,i+FS_Y+1,col1,files[i].name);

      sel = 0;
      vis = 0;
      dcolor(50,FS_Y+sel+1,70,FS_Y+sel+1,col2);

      do
      {
         if(vis>0) dprint(49,FS_Y+1,col1,"\x18");
         else dprint(49,FS_Y+1,col1,"\xDB");
         if((vis<cnt-FS_CNT-1) && (cnt>FS_CNT)) dprint(49,FS_Y+FS_CNT+1,col1,"\x19");
         else dprint(49,FS_Y+FS_CNT+1,col1,"\xDB");

         ch = getch();
         if(!ch)
         {
            ch = getch();
            switch(ch)
            {
               case 72:   // Cursor-up
                  if(sel>0)
                  {
                     dcolor(50,FS_Y+sel-vis+1,70,FS_Y+sel-vis+1,col1);
                     sel--;
                     if(sel<vis)
                     {
                        dmove(51,FS_Y+1,69,FS_Y+FS_CNT,51,FS_Y+2);
                        dfill(51,FS_Y+1,69,FS_Y+1,' ',col1);
                        if(files[sel].dir) dprintf(51,FS_Y+1,col1,"%s\\",files[sel].name);
                        else dprint(51,FS_Y+1,col1,files[sel].name);
                        vis--;
                     };
                     dcolor(50,FS_Y+sel-vis+1,70,FS_Y+sel-vis+1,col2);
                  };
                  break;
               case 80:  // Cursor-down
                  if(sel<cnt-1)
                  {
                     dcolor(50,FS_Y+sel-vis+1,70,FS_Y+sel-vis+1,col1);
                     sel++;
                     if(sel>vis+FS_CNT)
                     {
                        dmove(51,FS_Y+2,69,FS_Y+FS_CNT+1,51,FS_Y+1);
                        dfill(51,FS_Y+FS_CNT+1,69,FS_Y+FS_CNT+1,' ',col1);
                        if(files[sel].dir) dprintf(51,FS_Y+FS_CNT+1,col1,"%s\\",files[sel].name);
                        else dprint(51,FS_Y+FS_CNT+1,col1,files[sel].name);
                        vis++;
                     };
                     dcolor(50,FS_Y+sel-vis+1,70,FS_Y+sel-vis+1,col2);
                  };
                  break;
            };
         };
      } while(ch!=27 && ch!=13);

      if(ch == 13)
      {
         fnsplit(full,drive,path,name,ext);
         if(files[sel].dir)
         {
            if(!strcmp(files[sel].name,".."))
            {
               cp = path+strlen(path)-2;
               while(cp >= path && *cp!='\\') cp--;
               if(cp >= path) cp++;
               *cp = 0;
               sprintf(full,"%s%s%s%s",drive,path,name,ext);
            }
            else sprintf(full,"%s%s%s\\%s%s",drive,path,files[sel].name,name,ext);
         }
         else
         {
            sprintf(full,"%s%s%s",drive,path,files[sel].name);
            ende = 1;
         };
      };
   } while(ch!=27 && !ende);

   sec_free(files);
   drestore(save);
   sec_free(save);

   strcpy(mask,full);

   return(ende);
};

