Metropoli BBS
VIEWER: disked.c MODE: TEXT (ASCII)
/***
*disked.c - DISKED The DISK EDitor for MS(tm)-DOS.
*
*Copyright (c) 1991-1995, Gregg Jennings.  All wrongs reserved.
*   P O Box 200, Falmouth, MA 02541-0200
*
*Purpose:
*   Command module.
*
*Notice:
*   This progam may be freely used and distributed.  Any distrubution
*   with modifications must retain the above copyright statement and
*   modifications noted.
*   No pulp-publication, in whole or in part, permitted without
*   permission (magazines or books).
*******************************************************************************/

/*
   Versions:

   2.7   25-Dec-1994    'y': view .SAV file (some command letter changes)
   2.6   04-Sep-1994    ^T, find() changes, extern reference consolodation
   2.5   18-Apr-1994    cleaning up of extern defs
                        input/output function pointers
   2.4   23-Jan-1994    moved all startup code to SETUP.C
   2.3   19-Jan-1994    'removable' test
   2.2   16-Jan-1994    '^Q', replaced 'moved' with 'disk_moved'
   2.1   04-Jan-1994    Translate if !Files for startup, Borland
   2.0   28-Nov-1993

   Release Notes:

   Programming Notes:
*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>        /* _MAX_DIR */
#include <conio.h>         /* kbhit() */
#include <ctype.h>         /* isalpha() */
#include <dos.h>           /* _dos_set_drive() */
#include <io.h>            /* for exist() */
#include <direct.h>        /* getcwd(),chdir() */
#include <process.h>       /* spawnl() */

#include "disked.h"
#include "mylib.h"
#include "diskio.h"
#include "keys.h"
#include "alloc.h"
#include "files.h"
#include "error.h"
#include "dirent.h"
#include "direct.h"
#include "console.h"
#include "arrays.h"


/* for find() */

enum FIND_ARGUMENTS { F_BUFFER, F_DISK, F_CASE = 0, F_NOCASE };

struct Msg ps[]={          /* for inputing a two argument commnd */
   {" from ",6},
   {" number ",3},
};

struct Msg ap[]={          /* for inputing a two argument commnd */
   {" from ",3},
   {" number ",3}
};

struct Msg st[]={          /* three argument command 's' */
   {" track ",3},
   {" sector ",2},
   {" head ",1}
};

/* shared with SETUP.C only */

char comspec[FILENAME_MAX];      /* location of COMMAND.COM */
char promptvar[40];              /* DOS prompt variable */
char inifile[FILENAME_MAX];      /* INI file path/name */
char savfile[FILENAME_MAX];      /* Save file path/name */
char curdir[_MAX_DIR];           /* current working directory */
long set_sector;                 /* startup sector number */
int Save,Restore;
int files_indexed;

/* shared with SETUP.C and INIT.C */

int write_to;                    /* double protection on write */
unsigned long tagged[10];

/* shared with SETUP.C and DISKLIB.C */

int BigScreen;                   /* 50 line display */
unsigned int dir_cluster;        /* start up directory cluster nu. */

/* shared with many */

unsigned int byte_cnt;           /* buffer byte count */
unsigned int max_bytes;          /* maximum buffer size */
unsigned char *save_sec;         /* duplicate sector buffer */
unsigned char *spare_sec;        /* spare sector buffer */
unsigned char *data_buf;         /* pointer to area for data buffer */


#ifdef __BORLANDC__
#pragma argsused
#endif

#ifdef _MSC_VER
#pragma warning(disable:4035; disable:4100)
#endif



int main(int argc,char **argv)
{
unsigned int c;
char tmpstr[MAXSTR+1];
char ccurdir[_MAX_DIR];
unsigned int cdisk;
register unsigned int u;        /* vars for loops */
register int i;
unsigned int temps,tempt,temph,tempu;
long templ;
int tempd;
unsigned int bufptr;            /* pointer to file buffer */
int drives[MAX_DRIVE+1];        /* valid drive number array  1-MAX_DRIVE */
int noput;
char *bufferfull=" buffer full ";

   tmpstr[0] = '\0';
   bufptr = 0;
   noput = TRUE;

#ifdef __WATCOMC__
   setvbuf(stdout,NULL,_IONBF,0);      /* flush stdout every printf */
#endif

#ifndef NDEBUG
   printf("");    /* for alloc/free debugging; MSC will call malloc */
                  /* during first printf() */
#endif
   error.num = -1;

   cdisk = setup(argv,drives,&disk);
   startup(ccurdir,cdisk);

   /*
      The rest of the code is one huge switch/case in a loop.
      (It is so big that MSC gives: "main() too big for global
      optimizations", but I can't see trimming it any more.)

      The interface I chose to use, a TTY or Teletype-like
      interface (which may seem out dated to some be I find
      it extremely easy to use), presents some programming
      constructs that are hard to keep consistant and can
      be confusing :-)

      DISKED WILL NEVER HAVE A "WINDOWED" OR GUI INTERFACE!
      (colors and sound board support might cool though)
   */

   for (;;)
   {
      if (error.num != -1)
      {
         /*if (!Verify)*/        /* there's lots of these ' 's */
            output(' ');         /* it gets confusing and there may */
         printerror(Debug);      /* be others that aren't quite right */
      }
      if (disk_moved)
      {
         disk_moved = 0;
         dumpsector();
      }

      c = prompt(byte_cnt,Radix);

      /* translate movement keys if file tracking is on */

      if (trackfile(&c) == -1)
         continue;

      switch (c)
      {
         case '!':
            output(' ');                  /* if "File not found" */
            if (spawnl(P_WAIT,comspec,NULL)!=-1)
               disk_moved=1;              /* display sector on return */
            break;
         case F1:
            if (Files && n_files==1)
               print(" no files");
            else
            {
               print(" Current Directory: %s\n",curdir);
               directory();
            }
            break;
         case F2:
            if (!Files)
               break;
            if (n_files==1)
            {
               print(" no files");
               break;
            }
            for (u = 1; u < n_files; u++)       /* more than 32767 files ? */
            {
               print("\n%s",gfile(u));
               if (kbhit())
               {
                  if ((c=input())==0)
                     input();
                  else if (c==0x1b)
                     break;
                  else if (c==' ')
                     pause();
               }
           }
           break;

         case SHFTF1:
            dump(sec_buf,0,sec_size,128,Radix);
            break;
         case SHFTF2:
            dumpf(sec_buf,sec_size,Radix);
            break;
         case SHFTF3:
         case 'V'-'@':
            view(sec_buf,0,sec_size,NOPAUSE,Radix);
            break;
         case SHFTF4:
            dumpdir(sec_buf,sec_size);
            break;
         case SHFTF5:
            dumpboot(sec_buf);
            break;
         case SHFTF6:
            help();
            break;
         case SHFTF7:
            break;
         case F3:
            if (!Files)
               break;
            print(" %u Files, %u Directories",n_files-1,n_dirs);
            break;
         case F4:                        /* change dir */
            if (Display)
               print("directory ");
            else
               print("cd ");
            if (getstr(tmpstr,MAXSTR,_ALPHA) < 1)
               break;
            if (_chdir(tmpstr) == -1)
               print(" not found");
            _getcwd(curdir,_MAX_DIR);
            break;
         case F5:                        /* re-read */
            readsector();
            disk_moved = 1;
            break;
         case F6: case F7:
         case F8: case F9:
            if (byte_cnt > (max_bytes-sec_size))
               break;
            if (Display)
               print("append w/");
            tempt = temph = temps = 0;
            switch (c)
            {
               case F6:
                   if (Display)
                       print(StripTxt);
                   temph = 1;
                   break;
               case F7:
                   if (Display)
                       print(ConvertTxt);
                   temps = 1;
                   break;
               case F8:
                   if (Display)
                       print(MaskTxt);
                   tempt = 1;
                   break;
               case F9:
                   if (Display)
                       print("options");
                   tempt = Strip;
                   temph = Mask;
                   temps = Convert;
                   break;
               default:
                   break;
            }
            append(tempt,temph,temps,sec_buf,sec_size);
            break;
         case F0:
            if (!Files)
               break;
            if (n_files == 1)
            {
               print(" no files");
               break;
            }
            if (Display)
               print("goto ");
            print("file: ");
            if (getstr(tmpstr,MAXSTR,_ALPHA) < 1)
               break;
            if ((tempu = findfile(tmpstr)) != 0)
            {
               setcluster(tempu);
            }
            else
               print(" not found");
            break;
         case ALTA:case ALTC:case ALTD:
         case ALTF:case ALTG:case ALTH:case ALTL:
         case ALTM:case ALTP:case ALTS:case ALTB:
         case ALTV:case ALTW:case ALTT:
            setkeyword(c,kw);
            if (ft_track)
               Get = FALSE;
            break;

         case '*':
            Filter = !Filter;
            print("filter:%s",(Filter) ? "ON" : "OFF");
            break;

         case 'T'-'@':
            if (!Files) break;
            if (ft_track != 0)
            {
               filetrack(NULL,0);
               print(" file unlocked");
               break;
            }
            tempu = sectortocluster(log_sector);
            i = clusters[tempu];
            if (i > 0 && (unsigned)i <= n_files)
            {
               char *b;
               if (Display || Verify)
                  print(" track file ");
               if (Verify && !getver("",0))
                  break;
               print(" %s locked",b=gfile(i));
               if ((i = filetrack(b,i)) != 1)
                  print(" lock error %d",i);
            }
            break;

         /*  **** Display ****  */

         case '\n':
            header();
            break;
         case '\r':
            if (!Ascii && !BigScreen && Partial)
                  dump(sec_buf,(sec_size==128)?(0):(128),sec_size, \
                  (sec_size==512)?(384):(sec_size),Radix);
            else
               disk_moved = 1;
            break;

         case ' ':
            disk_moved = 1;
            break;
         case '\b':
            dparams(curdir);
            output('\n');
            break;
         case '/':
            disptext(command_text1);
            if (BigScreen)
               output('\n');
            else 
               break;
         case '?':
            disptext(command_text2);
            break;

         /*  **** movement ****  */

         case 'Q'-'@':                             /* go back */
            if (back_log_sector != log_sector)
            {
               if (Display)
                  print(" go back");
               setsector(back_log_sector);
               disk_moved = 1;
            }
            break;
         case 'H':                                 /* go root */
            if (Display)
               print(" root");
            rootsector();
            break;
         case HOME:                                /* go root or */
            if (Display)                           /*  go start */
               print(" home");
            if (set_sector != -1L)
               setsector(set_sector);
            else
               rootsector();
            break;
         case 'E':                                 /* go drive end */
         case END:
            if (Display)
               print(" end");
            lastsector();
            break;
         case 'b':                                 /* back sector */
         case UP:
            if (Display)
               print(" back sector");
            backsector();
            break;
         case 'n':                                 /* next sector */
         case DOWN:
             if (Display)
                 print(" next sector");
             nextsector();
             break;
         case 'B':                                 /* back cluster */
         case LEFT:
            if (Display)
               print(" back cluster");
            backcluster();
            break;
         case 'N':                                 /* next cluster */
         case RIGHT:
            if (Display)
               print(" next cluster");
            nextcluster();
            break;
         case 'B'-'@':                             /* back track */
         case PGUP:
            if (Display)
               print(" back track");
            backtrack();
            break;
         case 'N'-'@':                             /* next track */
         case PGDN:
            if (Display)
               print(" next track");
            nexttrack();
            break;
         case 'h':                                 /* next head */
            if (max_head==1)
               break;
            if (Display)
               print(" next head");
            nexthead();
            break;
         case 'r':                                 /* range (continuous) */
         case 'R':
         case CTRLR:
            if (c=='R')
               tempd=secs_cluster;
            else
               tempd=1;
            if (Display)
            {
               print(" range ");
               if (c==CTRLR)
                  output('-');
               putbyte(tempd);
            }
            tempd *= (c==CTRLR) ? -1 : 1;
            range(tempd);
            break;
         case '-':                                 /* plus/minus sectors */
         case '+':
         case '=':
            if (Display)
               print( (c=='-') ? " move back " : " move ahead ");
            if (getlnumb(num_sectors,&templ) <= 0)
               break;
            if (templ == 0)
               break;
            if (c=='-')
               templ *= -1;
            movesector(templ);
            break;
         case 'S'-'@':                             /* set to sector */
            if (Display)
               print(" sector ");
            if (getlnumb(num_sectors,&templ) <= 0)
               break;
            setsector(templ);
            break;
         case 'S':                                 /* set to cluster */
            if (Display)
               print(" cluster ");
            if (getnumb(num_clusters,&tempu) <= 0)
               break;
            if (tempu < 2)
               break;
            setcluster(tempu);
            break;
         case 's':                                 /* set physical */
            tempt=track;
            temps=sector;
            temph=head;
            c=set(st,(int *)&tempt,(int *)&temps,(int *)&temph);
            if (c=='f')
               fatsector();
            else if (c=='b')
               bootsector();
            else if (c==0)
               break;
            else
            {
               if (tempt > max_track)
                  tempt = track;
               if (temps > max_sector || temps==0)
                  temps = sector;
               if (temph >= max_head)
                  temph = head;
               if (tempt==track && temps==sector && temph==head)
                  break;
               setphysical(tempt,temps,temph);
             }
             break;
         case SRIGHT:                              /* back/next free cluster */
         case SLEFT:
            if (!Files)
               break;
            tempu=sectortocluster(log_sector);
            if (tempu==0)
               tempu=2;
            temps = (c==SLEFT) ? (-1) : (1);
            if (Display)
            {
               print( (temps==1) ? " next" : " back");
               print(" free cluster");
            }
            for (u=tempu+temps;;u+=temps)
            {
               if (u>=num_clusters)
                   u=2;
               if (u<2)
                   u=num_clusters;
               if (u==tempu)
                   break;
               if (clusters[u] < 1)
               {
                   setcluster(u);
                   break;
               }
            }
            break;
         case CEND:                                /* end of file */
            if (!Files)
               break;
            tempu = sectortocluster(log_sector);
            if (clusters[tempu] > 0 && (unsigned)clusters[tempu] <= n_files)
            {
               if (Display)
                  print(" end file");
               if ((tempu=arraylast(clusters,num_clusters,clusters[tempu])) == 0)
                  break;
               setcluster(tempu);
            }
            break;
         case CHOME:                               /* start of file */
            if (!Files)
               break;
            tempu=sectortocluster(log_sector);
            if (clusters[tempu] > 0 && (unsigned)clusters[tempu] <= n_files)
            {
               if (Display)
                  print(" home file");
               tempu=arrayfirst(clusters,num_clusters,clusters[tempu]);
               if (tempu == num_clusters)
                  break;
               setcluster(tempu);
            }
            break;
         case 'j':                                 /* back/next file cluster */
         case 'J':
         case CLEFT:
         case CRIGHT:
            if (!Files)
               break;
            tempu = sectortocluster(log_sector);      /* get current cluster */
            temps = (c=='j' || c==CRIGHT) ? 1 : -1;   /* set direction */
            if (clusters[tempu] == 0)
               break;
            if ((u = arraytrav(clusters,num_clusters,tempu,temps)) == tempu)
               break;                                 /* just one cluster? */
            if (Display)
            {
               print((temps==1)?" next":" back");
               print(" file's cluster");
            }
            setcluster(u);                         /* got it */
            break;

          /*  **** Buffer stuff ****  */

         case 'a':
             if (byte_cnt==max_bytes)
                 break;
             if (Display)
                 print(" append sector");
             if ((byte_cnt+sec_size)>max_bytes)
             {
                 print(bufferfull);
                 tempu=max_bytes-byte_cnt;
             }
             else
                 tempu=sec_size;
             memcpy(data_buf+byte_cnt,sec_buf,tempu);
             byte_cnt+=tempu;
             break;
         case 'A':
            if (log_sector<=data_sector)
               break;
            if (byte_cnt==max_bytes)
               break;
            if (Display)
               print(" append cluster");
            savesector();

            i=clustersector(log_sector);  /* goto 1st sector */
            if (movesector(-i) != DISK_OK)
            {
               restoresector();
               break;
            }
            for (u=0;;u++)                     /* get it loop */
            {
               if ((byte_cnt+sec_size)>max_bytes)
                  tempu=max_bytes-byte_cnt;
               else
                  tempu=sec_size;
               memcpy(data_buf+byte_cnt,sec_buf,tempu);
               if ((byte_cnt+=tempu)==max_bytes)
               {
                   print(bufferfull);
                   break;
               }
               if (u == secs_cluster-1)
                   break;
               if (nextsector() != DISK_OK)
                  break;
            }
            restoresector();
            if (readsector() != DISK_OK)
               disk_moved = 1;
            break;
         case 'A'-'@':
            if (byte_cnt==max_bytes) break;
            if (Display)
               print(" append bytes");
            tempd=temps=0;  /* tempd=from, temps=number */
            if (!get(ap,&tempd,(int *)&temps))
               break;
            if ((temps+tempd > sec_size) || temps==0)
               break;
            if (byte_cnt+temps > max_bytes)
               break;
            memcpy(data_buf+byte_cnt,sec_buf+tempd,temps);
            if ((byte_cnt+=temps)==max_bytes)
               print(bufferfull);
            break;
         case 'u':
         case 'U':
            if (byte_cnt==0)
                break;
            if (Display)
            {
                print(" unappend ");
                print((c=='u')?"sector":"cluster");
            }
            tempu = (c=='u') ? sec_size : cluster_size;
            if (byte_cnt < tempu)
               byte_cnt = 0;
            else
               byte_cnt-=tempu;
            break;
         case 'U'-'@':
            if (byte_cnt==0)
                break;
            if (Display)
                print(" unappend bytes ");
            if (getnumb(byte_cnt,&tempu)<=0)
                break;
            if (byte_cnt < tempu)
                byte_cnt=0;
            else
               byte_cnt-=tempu;
            break;
         case 'e':
         case 'E'-'@':
            if (byte_cnt==0)
               break;
            if (Display || Verify)
               print(" empty buffer");
            if (c=='e' && Verify && !getver("",0))
               break;
            bufptr=byte_cnt=0;
            break;
         case 'k':
            if (save_sec==NULL)
               break;
            if (Display)
               print(" kill changes");
            if (Verify && !getver("",0))
               break;
            memcpy(sec_buf,save_sec,sec_size);
            disk_moved=1;
            break;
         case '>':
            if (spare_sec==NULL)
               break;
            if (Display || Verify)
               print(" store sector");
            if (Verify && !getver("",0))
               break;
            memcpy(spare_sec,sec_buf,sec_size);
            noput=FALSE;
            break;
         case '<':
            if (spare_sec == NULL)
               break;
            if (noput)
            {
               print(" no sector stored");
               break;
            }
            if (Display || Verify)
               print(" retrieve sector");
            if (Verify && !getver("",0))
               break;
            memcpy(sec_buf,spare_sec,sec_size);
            disk_moved = 1;
            break;
         case 'd':
         case 'v':
            if (byte_cnt == 0)
               break;
            if (Display)
            {
               print((c == 'd') ? " dump" : " view");
               print(" file buffer from ");
            }
            if ((tempd = getlnumb(byte_cnt,&tempu)) == ABORT)
               break;
            if (tempd > 0)
               bufptr = tempu;
            if (c == 'd')
            {
               output('\n');
               bufptr = dump(data_buf,bufptr,byte_cnt,256,Radix);
               output('\n');
            }
            else
               bufptr = view(data_buf,bufptr,byte_cnt,PAUSE,Radix);
            break;
         case 'c':
            if (Display)
               print(" change sector buffer from ");
            if (change(sec_buf,sec_size,Radix))
               disk_moved = 1;
            break;
         case 'C':
            if (!byte_cnt)
               break;
            if (Display)
               print(" change file buffer from ");
            change(data_buf,byte_cnt,Radix);
            break;
         case 'D'-'@':
         case 'C'-'@':
            if (changedir(sec_buf,sec_size))
               disk_moved = 1;
            break;
         case 'g':           /*** get sectors ***/
         case 'G'-'@':       /* uses tempd, tempt, i */
            if (byte_cnt == max_bytes)    /* full? */
               break;
            if (Display)                  /* display */
            {
               print(" get sectors ");
               if (c == 'G'-'@' || Get)
                   print("w/move ");
            }                             /* get number */
            if (getbyte(&tempu) <= 0)
               break;                     /* tempd = number to get */
            savesector();
            if (tempu==0)                 /* 0 = get whole track from beginning */
            {
               tempu=max_sector;          /* count to get */
               log_sector=logicalsector(track,1,head);
            }
            else if (tempu == 1)              /* get rest of track */
               tempu = (max_sector - sector) + 1;

            if (log_sector == 0)
               log_sector = num_sectors-1;
            else
               --log_sector;
            if (Display)
               output(' ');
            for (i = 1 ; i <= (int)tempu ; i++)
            {
               if (kbhit())
                   break;
               if (Display)
               {
                  pn(i,Radix);
                  put(len(i),8);
               }
               if ((tempd=nextsector()) != DISK_OK)
               {
                  savecursor();
                  if (!Display)
                     output(' ');
                  printerror(Debug);
                  if (!getver("continue",0))
                  {
                     put(3,8);
                     break;
                  }
                  restcursor();
                  clreol();
               }
               if ((byte_cnt+sec_size)>max_bytes)
                   break;
               memcpy(data_buf+byte_cnt,sec_buf,sec_size);
               if ((byte_cnt+=sec_size)==max_bytes)
               {
                  print(bufferfull);
                  break;
               }
            }
            if (Display && tempd == DISK_OK)
               clreol();
            if (Get || c=='G'-'@')
               nextsector();
            else
            {
               restoresector();
               readsector();
               disk_moved = 0;
            }
            break;

         /*  **** Log Drive ****  */

         case 'l':
         case 'L'-'@':
            if (c == 'l')
            {
               if (Display)
                   print(" disk ");
               c = input();
               if (!isalpha(c))
                   break;
               tempd = toupper(c)-'@';
               if (drives[tempd]!=TRUE)
                   break;
               output(toupper(c));
               output(':');
               if (Verify)
               {
                  if (!getver("log disk",MOV_YN))
                     break;
               }
            }
            else
               tempd = disk;
            if (newdisk(tempd))
            {
               disk = tempd;
               if (avail_clusters == 0)
                  avail_clusters = get_avail_clusters();
               dparams(curdir);
            }
            if (error.num != -1)    /* if theres gonna be an error */
            {
               if (disk_moved == 1)
               {
                  output('\n');       /* put it on a new line */
                  output('\n');
               }                    /* if its bad BOOT, reset diskio flag */
               if (strcmp(error.func,"diskio") == 0)
                  diskio_error = 0;
            }
            break;

         /*  **** Misc. ****  */

         case 'T':
            for (i=1;i<10;i++)
               if (tagged[i]!=0L)
                   break;
            if (i<10)
            {
               if (Display)
                  print(" tagged sector list");
               for (i=1;i<10;i++)
               {
                  if (!tagged[i])
                     continue;
                  output(' ');
                  output(i+'0');
                  output(':');
                  pln(tagged[i],Radix);
               }
            }
            else if (Display)
               print(" no tagged sectors");
            break;
         case 't':
            if (Display)
               print(" number of this tag? ");
            if ((c=input()) < '0' || c > '9')
               break;
            output(c);
            if (c == '0')
            {
               if (getver(" clear all",0))
                  memset(tagged,0,sizeof(tagged));
               break;
            }
            tagged[c-'0']=log_sector;
            break;
         case 'f':
         case '\\':
            if (Display)
               print(" find ");
            tempd = find(F_DISK,1,(c=='f') ? F_CASE : F_NOCASE);
            if (tempd>=0)
            {
               print("\nfound at ");
               pn(tempd,Radix);
            }
            if (tempd!=ABORT)             /* user pressed ESC */
               readsector();
            break;
         case 'F':
         case 'F'-'@':
            if (byte_cnt==0)
               break;
            if (Display)
               print(" find ");
            if (find(F_BUFFER,1,(c=='F') ? F_CASE : F_NOCASE) == -1)
               print(" not found");
            break;
         case 'P':
            if (Display)
               print(" put");
            templ=log_sector;
            temps=0;               /* templ=from, temps=number */
            if (!getl(ps,&templ,(int *)&temps))
               break;
            if (templ+(long)temps > (long)num_sectors)
               break;
            if (Display)
               print(" file: ");
            else
               output(':');
            if (getstr(tmpstr,64,_ALPHA) > 0)
            {
               if (Verify)
               {
                  if (!getver(" put file",MOV_YN))
                     break;
               }
               if (exist(tmpstr))
               {
                  savecursor();
                  if (!Verify)
                     output(' ');
                  if (!getver("exists, overwrite",MOV_YN))
                     break;
                  restcursor();
                  clreol();
               }
               if (error.num == -1)
               {
                  if (Display && !Verify)
                     output(' ');
                  else if (Display && Verify)
                  {
                     put(3,' ');
                     put(3,8);
                  }
                  putsectors(tmpstr,templ,temps);
                  readsector();
               }
            }
            break;
         case 'P'-'@':
         case 'p':
            if (byte_cnt==0)
               break;
            if (Display)
               print(" file: ");
            getstr(tmpstr,64,_ALPHA);
            if (!tmpstr[0])
               break;
            if (Verify)
            {
               print(" put file ");
               if (Display && c=='p')
                  print("w/options");
               else if (Display)
                  print("w/o options");
               if (!getver("",MOV_YN))
                  break;
            }
            if (access(tmpstr,0) == 0)
            {
               savecursor();
               if (!Verify)
                  output(' ');
               if (!getver("exists, overwrite",MOV_YN))
                  break;
               restcursor();
               clreol();
               if (unlink(tmpstr) == -1)
                  break;
            }
            if (error.num != -1)
               break;
            if (Display)
            {
               savecursor();
               if (!Verify)
                  output(' ');
               print("putting");
               restcursor();
            }
            putfile(tmpstr,(c=='p') ? XLATE : NOXLATE,Mask,Strip,Convert);
            break;
         case 'I'-'@':
         case 'i':
            if (byte_cnt==max_bytes)
               break;
            if (Display)
               print(" file: ");
            getstr(tmpstr,64,_ALPHA);
            if (!tmpstr[0])
               break;
            if (Verify)
            {
               print(" insert file ");
               if (Display && c=='i')
                  print("w/options");
               else if (Display)
                  print("w/o options");
               if (!getver("",MOV_YN))
                  break;
            }
            if (Display)
            {
               savecursor();
               if (!Verify)
                  output(' ');
               print("inserting");
               restcursor();
            }
            tempd=getfile(tmpstr, (c=='i') ? XLATE : NOXLATE,Mask,Strip,Convert);
            if (tempd == -2)
            {
               if (!Verify)
                  output(' ');
               print("buffer full ");
            }
            break;
         case 'w':
            if (!write_to || !Write)
            {
               print(" write not enabled");
               break;
            }
            if (Display || Verify)
               print(" write sector");
            if (log_sector<dir_sector)
            {
               print("\a Warning! This is ");
               print((log_sector==0)?"the BOOT":"a FAT");
               print(" sector, ");
               if (!getver("write anyway",0))
                   break;
            }
            else if (Verify && !getver("",0))
               break;
            writesector();
            break;
         case 'z':
         case 'Z':
            if (Display || c=='Z')
            {
               if (Display)
                   print(" parameters");
               dkey(kw);
               if (c=='z')
                   output('\n');
               else
                   break;
            }
            if (getstr(tmpstr,MAXSTR,_LOWER|_UPPER)>0)
               ckey(tmpstr,kw);
            break;
         case '0':case '1':case '2':case '3':
         case '4':case '5':case '6':case '7':
         case '8':case '9':
            c-=0x30;
            if (!tagged[c])
               break;
            if (Display || Verify)
            {
               print(" goto sector ");
               pln(tagged[c],Radix);
            }
            if (Verify && !getver("",0))
               break;
            if (log_sector != tagged[c])
            {
               log_sector = tagged[c];
               readsector();
               disk_moved = 1;
            }
            break;
         case ',':       /* toggle radix */
            if (Radix==10)
               Radix=16;
            else
               Radix=10;
            if (Display)
            {
               print(" radix is now ");
               print((Radix==16)?"hex":"dec");
            }
            break;
         case 'D':
            if (Debug)
               debug();
            break;
         case 'm':
            if (!Files)
               break;
            tempu = sectortocluster(log_sector);
            if (clusters[tempu] > 0 && (unsigned)clusters[tempu] <= n_files)
            {
               if (Display)
                   print(" map file ");
               print(gfile(clusters[tempu]));
               output('\n');
               arraymap(clusters,num_clusters,clusters[tempu],Radix);
            }
            break;
         case 'M':
            if (Files)
            {
               if (Display)
                   print(" map free space");
               output('\n');
               if (arraymap(clusters,num_clusters,0,Radix) == 0)
                  print(" no free space");
            }
            break;
         case 'I':
            if (!Files)
               break;
            tempd = sectortocluster(log_sector);
            if (clusters[tempd] < 0 || clusters[tempd] > (int)n_files)
               break;
            if (files[clusters[tempd]].dir)
            {
               print(" can not insert directories");
               break;
            }
            sprintf(tmpstr,gfile(clusters[tempd]));
            if (Display)
            {
               print(" insert file ");
               print(tmpstr);
            }
            if (Verify)
            {
               if (!getver("",0))
                  break;
            }
            if (Display)
            {
               savecursor();
               if (!Verify)
                  output(' ');
               print("inserting");
               restcursor();
            }
            if (getfile(tmpstr,XLATE,Mask,Strip,Convert) == -2)
            {
               if (!Verify)
                  output(' ');
               print("buffer full ");
            }
            break;

         case 'Y'-'@':
            if (Display && !Verify)
               print(" saving");
            else if (Verify && !getver(" save",0))
               break;
            saveinit(savfile);
            break;
         case 'Y':
            if (Display && !Verify)
               print(" restoring");
            else if (Verify && !getver(" restore",0))
               break;
            tempd = Home;
            Home = FALSE;
            tempt = disk;
            templ = log_sector;
            if (getinit(savfile,INIT_RESTORE))
            {
               if (tempt != disk)
               {
                  if (!newdisk(disk))
                  {
                     disk = tempt;
                     log_sector = templ;
                  }
               }
               else if ((unsigned long)templ != log_sector)
                  readsector();
               else if (Display)
                  output('\n');
               disk_moved = 1;
            }
            else
            {
               disk = tempt;
               log_sector = tempu;
            }
            Home = tempd;
            break;
         case 'x':
            viewfile(inifile,Display);
            break;
         case 'y':
            getinit(savfile,INIT_VIEW);
            break;

         case 'q':
         case '.':
         case ESC:
         case ALTX:
            if (Display || Verify)
               print(" exit DISKED");
            if (c != ALTX && Verify && !getver("",0))
               break;
            _dos_setdrive(cdisk,&tempu);
            if (ccurdir[0])
               _chdir(ccurdir);
            if (Save && c != ALTX)
            {
               if (Verify)
                  if (!getver(" save",1))
               break;
               if (Display)
                  print(" saving...");
               saveinit(savfile);
            }
            if (files_indexed)            /* free calls are for an IDE */
            {                             /* such as QuickC that I use */
               hugefreep(files);          /* which can get confused if */
               hugefreep(clusters);       /* if you don't do this */
            }
            if (spare_sec)
               freep(spare_sec);
            if (save_sec)
               freep(save_sec);
            freep(sec_buf);
            freep(data_buf);
            exit(0);
            break;
         default:
             break;
        }
    }
}
[ RETURN TO DIRECTORY ]