//   filedemo.h
//
//   filedemo.h contains the necessary includes, constants, and function
//   prototypes (for functions provided in the main program) that are used
//   by all files involved in the file demonstration system. In addition,
//   filedemo.h caontains the declarations of all classes that are used by
//   every file access method (i.e. not specific to a single access method).
//   The actual definitions for the member functions of these classes, those
//   more than one line in length, are contained in filedemo.cpp


#include <graphics.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <string.h>


const CHAR_WID = 4;        //  characters are four pixels wide
const WIDTH = 100;         //  width of each block location in pixels
const CYLS = 4;            // number of cylinders per disk
const TRKS = 4;            // number of tracks per cylinder
const BLKS = 3;            // number of blocks per track
const SECS = 3;            // number of sectors per block
const BLK_SIZE = 20;       // number of characters per disk block
const SEC_SIZE = 6;        // number of characters per sector
const OV_SIZE = 2;         // number of characters in overflow pointer
const NUM_BLKS = 48;       // total number of disk blocks
const DISK_SCR_WID = 320;  // 320 pixels for width of disk window
const MAXLINE = 80;        // maximum number of characters per line


void wait (void);
void quit (void);
void draw_init (void);
void draw_fileopen (void);
void draw_all (void);





//    class external
//
//    The class external provides a simulated disk drive which is
//    displayed onscreen in an opened window for visual observation
//    by the user. This simulated disk contains 4 cylinders, each
//    cylinder containing 4 tracks. A track holds 3 blocks with each
//    block containing 3 sectors and an overflow pointer. A sector
//    is drawn as 6 characters and an overflow pointer as 2 characters.
//    However, the user accesses the disk by reading and writing blocks
//    of 20 characters and can actually use and organize those 20
//    characters in any way desired. With 4 cylinders, 4 tracks/cylinder,
//    and 3 blocks/track, a total of 48 blocks (4 * 4 * 3) are provided.

class external
   {
   private:
      char blk [NUM_BLKS] [BLK_SIZE + 1];  // actual storage array to
					   // permanently hold the (char) data
   public:
      external (void);                     // external constructor
      void read_blk (int blk_no, char* buffer)    // read a block number
	 { strcpy (buffer, blk[blk_no]); }
      void write_blk (int blk_no, char* buffer);  // write to a block number
      void draw (void);                    // draw the disk onscreen
   };





//   class block
//
//   The class block is an abstract class used to build all of the internal
//   data structures for the file system. It provides a basic on screen
//   structure consisting of n number of rectangles all stacked one on top
//   of each other. The capability is also provided to specify the on screen
//   location of the block, as well as a title to be written above it.
//   Also the member function write allows each rectangle (line number) to
//   be written into.

class block
   {
   private:
      int x, y;            // coordinates for upper left corner of block
      int n;               // number of lines (rectangles) in block
      char title [30];     // block title (written above the block)

   public:
      block (int NewN, char* NewTitle);        // block constructor
      void location (int NewX, int NewY);      // establish block location
      void draw (void);                        // draw the block on the screen
      void write (int line_no, char* textstr); // write to a block
   };                                          //      location





//   class iobcb
//
//   The IO buffer control block class is derived from the block class.
//   Put and Get member functions are provided to load and read each element
//   in the block, as welll as a draw member function to draw the block.

class iobcb : public block
   {
   private:
      char pbn [WIDTH/CHAR_WID];
      char lbn [WIDTH/CHAR_WID];
      char modified [WIDTH/CHAR_WID];
      char bufsize [WIDTH/CHAR_WID];

   public:
      iobcb (char* NewTitle) : block (4, NewTitle)
	 { }
      void put_pbn (char* textstr)
	 { strcpy (pbn, textstr); }
      void put_lbn (char* textstr)
	 { strcpy (lbn, textstr); }
      void put_modified (char* textstr)
	 { strcpy (modified, textstr); }
      void put_bufsize (char* textstr)
	 { strcpy (bufsize, textstr); }
      void get_pbn (char* textstr)
	 { strcpy (textstr, pbn); }
      void get_lbn (char* textstr)
	 { strcpy (textstr, lbn); }
      void get_modified (char* textstr)
	 { strcpy (textstr, modified); }
      void get_bufsize (char* textstr)
	 { strcpy (textstr, bufsize); }
      void draw (void);
   };





//   class iobuf
//
//   The IO buffer block class is derived from the block class.
//   Put and Get member functions are provided to load and read each element
//   in the block, as welll as a draw member function to draw the block.

class iobuf : public block
   {
   private:
      char bufr [WIDTH/CHAR_WID];

   public:
      iobuf (char* NewTitle) : block (1, NewTitle)
	 { }
      void put_bufr (char* textstr)
	 { strcpy (bufr, textstr); }
      void get_bufr (char* textstr)
	 { strcpy (textstr, bufr); }
      void draw (void);
   };





//   class dct
//
//   The device control table block class is derived from the block class.
//   Put and Get member functions are provided to load and read each element
//   in the block, as welll as a draw member function to draw the block.

class dct : public block
   {
   private:
      char devstat [WIDTH/CHAR_WID];
      char posretry [WIDTH/CHAR_WID];
      char rdretry [WIDTH/CHAR_WID];
      char wrretry [WIDTH/CHAR_WID];
      char retrycnt [WIDTH/CHAR_WID];

   public:
      dct (char* NewTitle) : block (5, NewTitle)
	 { }
      void put_devstat (char* textstr)
	 { strcpy (devstat, textstr); }
      void put_posretry (char* textstr)
	 { strcpy (posretry, textstr); }
      void put_rdretry (char* textstr)
	 { strcpy (rdretry, textstr); }
      void put_wrretry (char* textstr)
	 { strcpy (wrretry, textstr); }
      void put_retrycnt (char* textstr)
	 { strcpy (retrycnt, textstr); }
      void get_devstat (char* textstr)
	 { strcpy (textstr, devstat); }
      void get_posretry (char* textstr)
	 { strcpy (textstr, posretry); }
      void get_rdretry (char* textstr)
	 { strcpy (textstr, rdretry); }
      void get_wrretry (char* textstr)
	 { strcpy (textstr, wrretry); }
      void get_retrycnt (char* textstr)
	 { strcpy (textstr, retrycnt); }
      void draw (void);
   };





//   class iorq
//
//   The IO reuqest queue block class is derived from the block class.
//   Put and Get member functions are provided to load and read each element
//   in the block, as welll as a draw member function to draw the block.

class iorq : public block
   {
   private:
      char stat [WIDTH/CHAR_WID];
      char hdpos [WIDTH/CHAR_WID];
      char hddir [WIDTH/CHAR_WID];

   public:
      iorq (char* NewTitle) : block (3, NewTitle)
	 { }
      void put_stat (char* textstr)
	 { strcpy (stat, textstr); }
      void put_hdpos (char* textstr)
	 { strcpy (hdpos, textstr); }
      void put_hddir (char* textstr)
	 { strcpy (hddir, textstr); }
      void get_stat (char* textstr)
	 { strcpy (textstr, stat); }
      void get_hdpos (char* textstr)
	 { strcpy (textstr, hdpos); }
      void get_hddir (char* textstr)
	 { strcpy (textstr, hddir); }
      void draw (void);
   };





//   class uicb
//
//   The user interface control block class is derived from the block class.
//   Put and Get member functions are provided to load and read each element
//   in the block, as welll as a draw member function to draw the block.

class uicb : public block
   {
   private:
      char id [WIDTH/CHAR_WID];
      char filename [WIDTH/CHAR_WID];
      char filetype [WIDTH/CHAR_WID];
      char opreq [WIDTH/CHAR_WID];
      char indexnum [WIDTH/CHAR_WID];
      char accmode [WIDTH/CHAR_WID];

   public:
      uicb (char* NewTitle) : block (6, NewTitle)
	 { }
      void put_id (char* textstr)
	 { strcpy (id, textstr); }
      void put_filename (char* textstr)
	 { strcpy (filename, textstr); }
      void put_filetype (char* textstr)
	 { strcpy (filetype, textstr); }
      void put_opreq (char* textstr)
	 { strcpy (opreq, textstr); }
      void put_indexnum (char* textstr)
	 { strcpy (indexnum, textstr); }
      void put_accmode (char* textstr)
	 { strcpy (accmode, textstr); }
      void get_id (char* textstr)
	 { strcpy (textstr, id); }
      void get_filename (char* textstr)
	 { strcpy (textstr, filename); }
      void get_filetype (char* textstr)
	 { strcpy (textstr, filetype); }
      void get_opreq (char* textstr)
	 { strcpy (textstr, opreq); }
      void get_indexnum (char* textstr)
	 { strcpy (textstr, indexnum); }
      void get_accmode (char* textstr)
	 { strcpy (textstr, accmode); }
      void draw (void);
   };





//   class userbuf
//
//   The user buffer block class is derived from the block class.
//   Put and Get member functions are provided to load and read each element
//   in the block, as welll as a draw member function to draw the block.

class userbuf : public block
   {
   private:
      char data [WIDTH/CHAR_WID];

   public:
      userbuf (char* NewTitle) : block (1, NewTitle)
	 { }
      void put_data (char* textstr)
	 { strcpy (data, textstr); }
      void get_data (char* textstr)
	 { strcpy (textstr, data); }
      void draw (void);
   };





//   class kdb
//
//   The key desrciption block class is derived from the block class.
//   Put and Get member functions are provided to load and read each element
//   in the block, as welll as a draw member function to draw the block.

class kdb : public block
   {
   private:
      char keysize [WIDTH/CHAR_WID];
      char keytype [WIDTH/CHAR_WID];

   public:
      kdb (char* NewTitle) : block (2, NewTitle)
	 { }
      void put_keysize (char* textstr)
	 { strcpy (keysize, textstr); }
      void put_keytype (char* textstr)
	 { strcpy (keytype, textstr); }
      void get_keysize (char* textstr)
	 { strcpy (textstr, keysize); }
      void get_keytype (char* textstr)
	 { strcpy (textstr, keytype); }
      void draw (void);
   };





//   class filecb
//
//   The file control block class is derived from the block class.
//   Put and Get member functions are provided to load and read each element
//   in the block, as welll as a draw member function to draw the block.

class filecb : public block
   {
   private:
      char filename [WIDTH/CHAR_WID];
      char stat [WIDTH/CHAR_WID];
      char physeof [WIDTH/CHAR_WID];
      char logeof [WIDTH/CHAR_WID];
      char maxrec [WIDTH/CHAR_WID];
      char blkfac [WIDTH/CHAR_WID];
      char lastop [WIDTH/CHAR_WID];
      char crp [WIDTH/CHAR_WID];

   public:
      filecb (char* NewTitle) : block (8, NewTitle)
	 { }
      void put_filename (char* textstr)
	 { strcpy (filename, textstr); }
      void put_stat (char* textstr)
	 { strcpy (stat, textstr); }
      void put_physeof (char* textstr)
	 { strcpy (physeof, textstr); }
      void put_logeof (char* textstr)
	 { strcpy (logeof, textstr); }
      void put_maxrec (char* textstr)
	 { strcpy (maxrec, textstr); }
      void put_blkfac (char* textstr)
	 { strcpy (blkfac, textstr); }
      void put_lastop (char* textstr)
	 { strcpy (lastop, textstr); }
      void put_crp (char* textstr)
	 { strcpy (crp, textstr); }
      void get_filename (char* textstr)
	 { strcpy (textstr, filename); }
      void get_stat (char* textstr)
	 { strcpy (textstr, stat); }
      void get_physeof (char* textstr)
	 { strcpy (textstr, physeof); }
      void get_logeof (char* textstr)
	 { strcpy (textstr, logeof); }
      void get_maxrec (char* textstr)
	 { strcpy (textstr, maxrec); }
      void get_blkfac (char* textstr)
	 { strcpy (textstr, blkfac); }
      void get_lastop (char* textstr)
	 { strcpy (textstr, lastop); }
      void get_crp (char* textstr)
	 { strcpy (textstr, crp); }
      void draw (void);
   };





//   class iorequest
//
//   The IO request block class is derived from the block class.
//   Put and Get member functions are provided to load and read each element
//   in the block, as welll as a draw member function to draw the block.

class iorequest : public block
   {
   private:
      char pbn [WIDTH/CHAR_WID];
      char priority [WIDTH/CHAR_WID];

   public:
      iorequest (char* NewTitle) : block (2, NewTitle)
	 { }
      void put_pbn (char* textstr)
	 { strcpy (pbn, textstr); }
      void put_priority (char* textstr)
	 { strcpy (priority, textstr); }
      void get_pbn (char* textstr)
	 { strcpy (textstr, pbn); }
      void get_priority (char* textstr)
	 { strcpy (textstr, priority); }
      void draw (void);
   };





//   class pointer
//
//   The pointer class allows for the drawing of a directed line segment
//   on the screen to simulate a pointer to a block. The class maintains
//   the location of the start and end points of the line segment. There
//   are member functions to set the location and to draw the pointer.

class pointer
   {
   private:
      int startx, starty;   // starting coordinate of line
      int endx, endy;       // ending coordinate of line

   public:
      void location (int NewStartx, int NewStarty, int NewEndx, int NewEndy);
      void draw (void);    // draw the pointer on the screen
   };





//   class acc_method
//
//   The class acc_method is a base class used to derive the five required
//   access methods. The member function close is identical for all five
//   access methods and is therefore defined in the base class. All other
//   access method functions are declared as virtual and defined in the
//   individual derived classes. The current position of the disk head is
//   maintained in the access method class. There are five protected member
//   functions (which are accessable to the derived classes) to set the
//   head position, update the head position (and direction), to move a
//   block from the disk to the IO buffer, to move a block from the IO
//   buffer to the disk, and to retrieve the current record pointer from
//   the file control block.

class acc_method
   {
   private:
      int hd_pos;     // the current position of the disk head

   protected:
      void set_hd_pos (int new_hd_pos)
	 { hd_pos = new_hd_pos; }

      void update_hdpos (iorq* iorq_ptr, int cur_hd_pos);

      void put_blk (iobuf* iobuf_ptr, iobcb* iobcb_ptr, iorq* iorq_ptr,
		    iorequest* iorequest_ptr, external* disk_ptr);

      void get_blk (iobuf* iobuf_ptr, iobcb* iobcb_ptr, iorq* iorq_ptr,
		    iorequest* iorequest_ptr, external* disk_ptr,
		    int blk_num);

      int get_cur_rec (filecb* filecb_ptr);

   public:
      void close (uicb* uicb_ptr, iobcb* iobcb_ptr, iobuf* iobuf_ptr,
		  iorq* iorq_ptr, iorequest* iorequest_ptr, external* disk_ptr);

      virtual void open (uicb* uicb_ptr, filecb* filecb_ptr, iobcb* iobcb_ptr,
		  iobuf* iobuf_ptr, iorq* iorq_ptr, iorequest* iorequest_ptr,
		  external* disk_ptr, char* accmode) = 0;

      virtual void create (uicb* uicb_ptr, userbuf* userbuf_ptr,
		    filecb* filecb_ptr, kdb* kdb_ptr, iobuf* iobuf_ptr,
		    external* disk_ptr, iobcb* iobcb_ptr, iorq* iorq_ptr,
		    iorequest* iorequest_ptr, char* progname, char* fname,
		    char* accmode) = 0;

      virtual int position (uicb* uicb_ptr, filecb* filecb_ptr,
		    iobuf* iobuf_ptr, iobcb* iobcb_ptr, iorq* iorq_ptr,
		    iorequest* iorequest_ptr, external* disk_ptr,
		    char* record) = 0;

      virtual void read (uicb* uicb_ptr, filecb* filecb_ptr,
		    iobuf* iobuf_ptr, iobcb* iobcb_ptr, iorq* iorq_ptr,
		    iorequest* iorequest_ptr, userbuf* userbuf_ptr,
		    external* disk_ptr, char* record) = 0;

      virtual void readnext (uicb* uicb_ptr, filecb* filecb_ptr,
		    iobuf* iobuf_ptr, iobcb* iobcb_ptr, iorq* iorq_ptr,
		    iorequest* iorequest_ptr, userbuf* userbuf_ptr,
		    external* disk_ptr) = 0;

      virtual void write (uicb* uicb_ptr, userbuf* userbuf_ptr,
		    filecb* filecb_ptr, iobuf* iobuf_ptr, iobcb* iobcb_ptr,
		    iorq* iorq_ptr, iorequest* iorequest_ptr,
		    external* disk_ptr, char* rec_no, char* record) = 0;

      virtual void del (uicb* uicb_ptr, filecb* filecb_ptr, iobuf* iobuf_ptr,
					    iobcb* iobcb_ptr) = 0;
   };
