#include "dbinc.h"
/*****************************************************************************
*                                                                            *
*      COMMON OCEANOGRAPHIC DATA ACCESS SYSTEM (CODAS)                       *
*                                                                            *
*      WRITTEN BY:  RAMON CABRERA, ERIC FIRING, and JULIE RANADA             *
*                   JOINT INSTITUTE FOR MARINE AND ATMOSPHERIC RESEARCH      *
*                   1000 POPE ROAD  MSB 404                                  *
*                   HONOLULU, HI 96822                                       *
*                                                                            *
*      VERSION:     3.00                                                     *
*                                                                            *
*      DATE:        APRIL 1989                                               *
*                                                                            *
*****************************************************************************/
/*

       FILE:  dbshow.c

              UTILITY FUNCTIONS FOR DISPLAYING DATABASE DATA/STATUS

*/
char buff[80];

/*-----------------------------------------------------------------------------

   FUNCTION:  SHDB

      It opens and shows a database.

   RETURNS:  VOID

*/
#if PROTOTYPE_ALLOWED
void SHDB(void)
#else
void SHDB()
#endif
{
   YMDHMS_TIME_TYPE t;
   DMSH_POSITION_TYPE d[2];
   DEPTH_RANGE_TYPE dr;
   int iansw, par[10], ier = 0, type;
   unsigned int nb, ofs;

   /** 1999/09/15 Pierre Jaccard
       Initializing max screen lines with compile time default 
   **/
   set_max_screen_lines(0);

   do
   {
      clear_screen();
      printf("\n\n BLK: %5d   OPEN: %1d    PRF: %5d   OPEN: %1d    IER: %6d\n",
         db->block_dir_index, db->block_is_open,
         db->profile_dir_index, db->profile_is_open, ier);
      printf("\n 1 - Show BLK DIR HDR          10 - SRCH TIME");
      printf("\n 2 - Show BLK DIR              11 - SRCH BLK/PRF");
      printf("\n 3 - Show BLK DIR ENTRY        12 - MOVE");
      printf("\n 4 - Show BLK HDR              13 - GET TIME");
      printf("\n 5 - Show PRF DIR              14 - GET POS");
      printf("\n 6 - Show PRF DIR ENTRY        15 - GET DEPTH RANGE");
      printf("\n 7 - Show DATA LIST            16 - GET DATA");
      printf("\n 8 - Show DATA DIR             17 - SET SCREEN SIZE");
      printf("\n 9 - Show STRUCT DEFN          18 - SHOW BLK FTR");
      printf("\n                      99 - QUIT");
      printf("\n\n\n ENTER CHOICE ===> ");
      scanf(" %d", &iansw); gets(buff);
      clear_screen();
      switch (iansw)
      {
         case 1:
            shbdh();
            break;
         case 2:
            shbd();
            break;
         case 3:
            shbde();
            break;
         case 4:
            shbh();
            break;
         case 5:
            shpd();
            break;
         case 6:
            shpde();
            break;
         case 7:
            shdl();
            break;
         case 8:
            shdd();
            break;
         case 9:
            shstrdef();
            break;
         case 10:
            do
            {
               printf("\n\n ENTER TIME ( Y M D H M S ) OR (year decimal-day) ===> ");
            } while (get_ymdhms_time(stdin, &t));
            type = TIME_SEARCH;
            DBSRCH(&type, (char *) &t, &ier);
            DBERROR(&ier, "DBSRCH\n\n");
            break;
         case 11:
            printf("\n\n ENTER BLOCK/PROFILE ( BLK#  PRF# ) ===> ");
            scanf("%d %d", par, par + 1);
            gets(buff);
            type = BLOCK_PROFILE_SEARCH;
            DBSRCH(&type, (char *) par, &ier);
            DBERROR(&ier, "DBSRCH\n\n");
            break;
         case 12:
            printf("\n\n ENTER # OF PROFILES TO MOVE ===> ");
            scanf("%d", par);
            gets(buff);
            DBMOVE(par, &ier);
            DBERROR(&ier, "DBMOVE\n\n");
            break;
         case 13:
            type = TIME;
            nb = sizeof(YMDHMS_TIME_TYPE);
            DBGET(&type, (char *) &t, &nb, &ier);
            DBERROR(&ier, "DBGET\n\n");
            printf("\n\n PROFILE TIME: ");
            print_ymdhms_time(stdout, &t);
            break;
         case 14:
            type = POSITION;
            nb = 2 * sizeof(DMSH_POSITION_TYPE);
            DBGET(&type, (char *) d, &nb, &ier);
            DBERROR(&ier, "DBGET\n\n");
            printf("\n\n PROFILE POSITION: LON --> ");
            print_dmsh_position(stdout, &d[0]);
            printf("\n                   LAT --> ");
            print_dmsh_position(stdout, &d[1]);
            break;
         case 15:
            type = DEPTH_RANGE;
            nb = sizeof(DEPTH_RANGE_TYPE);
            DBGET(&type, (char *)&dr, &nb, &ier);
            DBERROR(&ier, "DBGET\n\n");
            printf("\n\n PROFILE DEPTH RANGE: MIN --> %d",dr.min_depth);
            printf("\n                      MAX --> %d",dr.max_depth);
            break;
         case 16:
            clear_screen();
            printf("\n\n ENTER VARIABLE NAME or CODE ===> ");
            gets(buff);
            if (!sscanf(buff, " %d", &type) &&
               (type = get_data_list_index(buff)) == -1)
            {
               puts("\n\n *** VARIABLE NOT PRESENT ***");
               puts("\n\n ---Press enter to continue.---");
               getchar();
            }
            else
               shdata(type);
            break;
         case 17:
            printf("\n\n ENTER # OF LINES TO DISPLAY");
            printf("\n        <return> for default ===> ");
            gets(buff);
            if ( !(buff[0]) || !(sscanf(buff, " %d", par)) )
               set_max_screen_lines(20);
            else
               set_max_screen_lines(*par);
            break;
         case 18:
            printf("\n BLOCK FOOTER:\n\n");
            check_screen_lines(3);
            nb = db->block_hdr.block_nbytes - db->block_hdr.block_ftr_ofs;
            if (nb > 0)
            {
               if ( (db->block_ftr = malloc(nb)) == NULL )
               {
                  db->error_code = INSUFFICIENT_MEMORY;
                  db->error_data = BLOCK_FTR;
                  DBERROR(&(db->error_code), "SHDB\n\n");
               }
               type = BLOCK_FTR;
               DBGET(&type, db->block_ftr, &nb, &ier);
               DBERROR(&ier, "DBGET\n\n");
               ofs = 0;
               while (ofs < nb)
               {
                  printf("%c", *(ofs + db->block_ftr));
                  if (*(ofs + db->block_ftr) == 0xA)  /* linefeed */
                     check_screen_lines(1);
                  ofs++;
               }
            }
            else
            {
               puts("\n\n *** NOT PRESENT ***");
            }
            puts("\n\n ---Press enter to continue.---");
            getchar();
            break;
         default:
            break;
      }
      if (ier || (iansw > 12 && iansw < 16) || (iansw > 5 && iansw < 9) ||
         (iansw == 1 || iansw == 3 || iansw == 4))
      {
         puts("\n\n ---Press enter to continue.---");
         getchar();
      }
   } while (iansw != 99);
}

/*-----------------------------------------------------------------------------

   FUNCTION:  shbdh

      It shows the block directory header.

   RETURNS:  VOID

*/
#if PROTOTYPE_ALLOWED
void shbdh(void)
#else
void shbdh()
#endif
{
   printf("\n\n BLOCK DIRECTORY HEADER");
   printf("\n\ndb version: ");
   print_array_1s(stdout, db->block_dir_hdr.db_version, 4, 4, "%c");
   printf("\ndataset id: %s", (char *) &(db->block_dir_hdr.dataset_id));
   printf("\ntime:  ");
   prpckt(stdout, &(db->block_dir_hdr.time1));
   printf(" --- to --- ");
   prpckt(stdout, &(db->block_dir_hdr.time2));
   printf("\nlongitude: ");
   prpckp(stdout, &(db->block_dir_hdr.lon1));
   printf(" --- to --- ");
   prpckp(stdout, &(db->block_dir_hdr.lon2));
   printf("\nlatitude:  ");
   prpckp(stdout, &(db->block_dir_hdr.lat1));
   printf(" --- to --- ");
   prpckp(stdout, &(db->block_dir_hdr.lat2));
   printf("\ndepth: %d", db->block_dir_hdr.depth1);
   printf(" --- to --- %d", db->block_dir_hdr.depth2);
   printf("\ndirectory type -----> %ld", db->block_dir_hdr.dir_type);
   printf("\nentry nbytes -------> %d", db->block_dir_hdr.dir_entry_nbytes);
   printf("\nnumber of entries --> %d", db->block_dir_hdr.dir_nentries);
   printf("\nnext_seq_number ----> %ld", db->block_dir_hdr.next_seq_number);
   printf("\nblock file template > %s", db->block_dir_hdr.block_file_template);
   printf("\ndata_mask ----------> ");
   print_bit_pattern(stdout, (ULONG *) &(db->block_dir_hdr.data_mask));
   printf("\ndata_proc_mask -----> ");
   print_bit_pattern(stdout, (ULONG *) &(db->block_dir_hdr.data_proc_mask));
}

/*-----------------------------------------------------------------------------

   FUNCTION:  shbde

      It shows the current block directory entry.

*/
#if PROTOTYPE_ALLOWED
void shbde(void)
#else
void shbde()
#endif
{
   int i;
   static struct
   {
      STRUCT_DEF_HDR_TYPE h1;
      STRUCT_DEF_ELEM_TYPE e1[14];
      STRUCT_DEF_HDR_TYPE n;
   } bde[] =
   {
      "BLOCK DIR ENTRY"    , 14, "",
      "producer_id"        , ""           , TEXT_VALUE_CODE   , 32, "",
      "time1"              , ""           , ULONG_VALUE_CODE  ,  1, "",
      "time2"              , ""           , ULONG_VALUE_CODE  ,  1, "",
      "lon1"               , ""           , LONG_VALUE_CODE   ,  1, "",
      "lon2"               , ""           , LONG_VALUE_CODE   ,  1, "",
      "lat1"               , ""           , LONG_VALUE_CODE   ,  1, "",
      "lat2"               , ""           , LONG_VALUE_CODE   ,  1, "",
      "depth1"             , ""           , SHORT_VALUE_CODE  ,  1, "",
      "depth2"             , ""           , SHORT_VALUE_CODE  ,  1, "",
      "block_nbytes"       , ""           , ULONG_VALUE_CODE  ,  1, "",
      "file_id"            , ""           , LONG_VALUE_CODE   ,  1, "",
      "data_mask"          , ""           , ULONG_VALUE_CODE  ,  1, "",
      "data_proc_mask"     , ""           , ULONG_VALUE_CODE  ,  1, "",
      "unassigned"         , ""           , LONG_VALUE_CODE   ,  1, "",
      ""                   , 0, ""
   };
   static FORMAT_SPEC bde_fmt[] =
   {
      "\n\nproducer id:  %.32s" , 0, NULL,
      "\ntime:  "          , 0, prpckt,
      " --- to --- "       , 0, prpckt,
      "\nlongitude: "      , 0, prpckp,
      " --- to --- "       , 0, prpckp,
      "\nlatitude:  "      , 0, prpckp,
      " --- to --- "       , 0, prpckp,
      "\ndepth: %d"        , 0, NULL,
      " --- to --- %d"     , 0, NULL,
      "\nblock nbytes -------> %ld", 0, NULL,
      "\nfile id ------------> %ld", 0, NULL,
      "\ndata mask ----------> "   , 0, print_bit_pattern,
      "\ndata proc. mask ----> "   , 0, print_bit_pattern,
      "\n"                         , 0, NULL
   };

   for (i = 0; i < bde->h1.nelem; i++)
      *(FORMAT_SPEC **) (bde->e1[i].format_ptr) = &bde_fmt[i];
   printf("\n\n BLOCK DIRECTORY ENTRY:  %d", db->block_dir_index);
   print_structure(stdout, (char *) db->block_dir_entry_ptr, "BLOCK DIR ENTRY",
      sizeof(BLOCK_DIR_ENTRY_TYPE), (STRUCT_DEF_HDR_TYPE *) bde);
}

/*-----------------------------------------------------------------------------

   FUNCTION:  shbh

      It shows the block header.

   RETURNS:  VOID

*/
#if PROTOTYPE_ALLOWED
void shbh(void)
#else
void shbh()
#endif
{
   printf("\n\n BLOCK HEADER");
   printf("\n\ndb version: ");
   print_array_1s(stdout, db->block_hdr.db_version, 4, 4, "%c");
   printf("\nhost:       ");
   print_array_1s(stdout, db->block_hdr.producer_host, 4, 4, "%c");
   printf("\ndataset id: %.32s", (char *) &(db->block_hdr.dataset_id));
   printf("\nproducer id: %.32s", (char *) &(db->block_hdr.producer_id));
   printf("\ntime:  ");
   prpckt(stdout, &(db->block_hdr.time1));
   printf(" --- to --- ");
   prpckt(stdout, &(db->block_hdr.time2));
   printf("\nlongitude: ");
   prpckp(stdout, &(db->block_hdr.lon1));
   printf(" --- to --- ");
   prpckp(stdout, &(db->block_hdr.lon2));
   printf("\nlatitude:  ");
   prpckp(stdout, &(db->block_hdr.lat1));
   printf(" --- to --- ");
   prpckp(stdout, &(db->block_hdr.lat2));
   printf("\ndepth: %d", db->block_hdr.depth1);
   printf(" --- to --- %d", db->block_hdr.depth2);
   printf("\ndatalist offset ----> %ld", db->block_hdr.data_list_ofs);
   printf("\ndir      offset ----> %ld", db->block_hdr.dir_ofs);
   printf("\ndirectory type -----> %ld", db->block_hdr.dir_type);
   printf("\nlog10(time units per s)--> %d",  db->block_hdr.dir_time_flag);
   printf("\ndatalist nentries --> %d", db->block_hdr.data_list_nentries);
   printf("\ndir entry nbytes ---> %d", db->block_hdr.dir_entry_nbytes);
   printf("\ndir nentries -------> %d", db->block_hdr.dir_nentries);
   printf("\ndata dir nentries --> %d", db->block_hdr.data_dir_nentries);
   printf("\ndata_mask ----------> ");
   print_bit_pattern(stdout, (ULONG *) &(db->block_hdr.data_mask));
   printf("\ndata_proc_mask -----> ");
   print_bit_pattern(stdout, (ULONG *) &(db->block_hdr.data_proc_mask));
}

/*-----------------------------------------------------------------------------

   FUNCTION:  shpde

      It shows the current profile directory entry.

   RETURNS:  void

*/
#if PROTOTYPE_ALLOWED
void shpde(void)
#else
void shpde()
#endif
{
   YMDHMS_TIME_TYPE t;
   int profile_key_type;

   printf("\n\n PROFILE DIRECTORY TYPE: %ld  ENTRY---> %d",
      db->block_hdr.dir_type, db->profile_dir_index);
   if (db->block_hdr.dir_time_flag == DIR_TIME_IN_SECONDS)
   {
      printf("\ntime in seconds: %ld", db->profile_dir_entry_ptr->time);
      DIFTIM((YMDHMS_TIME_TYPE *)&(db->block_base_time),
         (YMDHMS_TIME_TYPE *)&t,
         (LONG *)&(db->profile_dir_entry_ptr->time));
   }
   else
   {
      printf("\ntime in hundredths of seconds: %ld", db->profile_dir_entry_ptr->time);
      HDIFTIM((YMDHMS_TIME_TYPE *)&(db->block_base_time),
         (YMDHMS_TIME_TYPE *)&t,
         (LONG *)&(db->profile_dir_entry_ptr->time));
   }
   printf("\nwhole time: ");
   print_ymdhms_time(stdout, &t);
   profile_key_type = db->block_hdr.dir_type % 10;
   if ((profile_key_type == 1) || (profile_key_type == 3))
   {
      printf("\nlongitude: ");
      prpckp(stdout, &(db->profile_dir_entry_ptr->lon));
      printf("\nlatitude:  ");
      prpckp(stdout, &(db->profile_dir_entry_ptr->lat));
   }
   if ((profile_key_type == 2) || (profile_key_type == 3))
   {
      printf("\ndepth: %d", db->profile_dir_entry_ptr->depth1);
      printf(" --- to --- %d", db->profile_dir_entry_ptr->depth2);
   }
   printf("\nprofile offset   %ld", db->profile_dir_entry_ptr->ofs);
}

/*-----------------------------------------------------------------------------

   FUNCTION:  shdl

      It shows the current data list.

   RETURNS:  VOID

*/
#if PROTOTYPE_ALLOWED
void shdl(void)
#else
void shdl()
#endif
{
   int i;
   static struct
   {
      STRUCT_DEF_HDR_TYPE h;
      STRUCT_DEF_ELEM_TYPE e[9];
      STRUCT_DEF_HDR_TYPE n;
   } data_list[] =
   {
      "DATA LIST", 9, "",
      "name", "none", TEXT_VALUE_CODE, 20, "",
      "units", "none", TEXT_VALUE_CODE, 12, "",
      "value_type", "none", SHORT_VALUE_CODE, 1, "",
      "access_type", "none", SHORT_VALUE_CODE, 1, "",
      "access_0", "none", ULONG_VALUE_CODE, 1, "",
      "access_1", "none", ULONG_VALUE_CODE, 1, "",
      "offset", "none", FLOAT_VALUE_CODE, 1, "",
      "scale", "none", FLOAT_VALUE_CODE, 1, "",
      "unassigned", "none", LONG_VALUE_CODE, 1, "",
      "", 0, ""
   };
   static FORMAT_SPEC dl_fmt[] =
   {
      " %-20s", 0, NULL,
      " %-7.7s", 0, NULL,
      "    %4d", 0, NULL,
      " %2d", 0, NULL,
      " %6ld", 0, NULL,
      " %6ld", 0, NULL,
      " %9.1g", 0, NULL,
      " %9.1g", 0, NULL,
      "\n", 0, NULL
   };

   for (i = 0; i < data_list->h.nelem; i++)
      *((FORMAT_SPEC **) (data_list->e[i].format_ptr)) = &dl_fmt[i];
   printf("\n\n DATA LIST  NENTRIES: %d\n", db->block_hdr.data_list_nentries);
   printf("\n # name                 units      v_ty ac    ac0    ac1    offset     scale");
   printf("\n----------------------------------------------------------------------------\n");
   check_screen_lines(6);
   for (i = 0; i < db->block_hdr.data_list_nentries; i++)
      if (db->data_list[i].access_type)
      {
         printf("%2d", i);
         print_structure(stdout, (char *) &(db->data_list[i]), "DATA LIST",
            db->block_hdr.data_list_nentries, (STRUCT_DEF_HDR_TYPE *) data_list);
         check_screen_lines(1);
      }
   printf("----------------------------------------------------------------------------\n");
}

/*-----------------------------------------------------------------------------

   FUNCTION:  shdd

      It shows the current data directory.

   RETURNS:  VOID

*/
#if PROTOTYPE_ALLOWED
void shdd(void)
#else
void shdd()
#endif
{
   int i;
   static struct
   {
      STRUCT_DEF_HDR_TYPE h;
      STRUCT_DEF_ELEM_TYPE e[2];
      STRUCT_DEF_HDR_TYPE n;
   } data_dir[] =
   {
      "DATA DIRECTORY", 2, "",
      "ofs"   , "none", LONG_VALUE_CODE, 1, "",
      "nbytes", "none", LONG_VALUE_CODE, 1, "",
      "", 0, ""
   };

   static FORMAT_SPEC dd_fmt[] =
   {
      {"   ofs : %06ld", 0, NULL},
      {"   nbytes : %06ld", 0, NULL}
   };

   for (i = 0; i < data_dir->h.nelem; i++)
      *((FORMAT_SPEC **) (data_dir->e[i].format_ptr)) = &dd_fmt[i];
   printf("\n\n DATA DIR NENTRIES: %d", db->block_hdr.data_dir_nentries);
   printf("\n-------------------------------------------");
   check_screen_lines(5);
   for (i = 0; i < db->block_hdr.data_dir_nentries; i++)
   {
      printf("\nentry : %02d", i);
      print_structure(stdout, (char *) &(db->data_dir[i]), "DATA DIRECTORY",
         db->block_hdr.data_dir_nentries, (STRUCT_DEF_HDR_TYPE *) data_dir);
      check_screen_lines(1);
   }
   printf("\n-------------------------------------------\n");
}

/*-----------------------------------------------------------------------------

    FUNCTION:  shstrdef

       Shows structure definition for a user-specified variable.

*/
#if PROTOTYPE_ALLOWED
void shstrdef(void)
#else
void shstrdef()
#endif
{
   STRUCT_DEF_HDR_TYPE *str_def;
   char struct_name[20];
   unsigned int i, nelem;
   static struct
   {
      STRUCT_DEF_HDR_TYPE h;
      STRUCT_DEF_ELEM_TYPE e[5];
      STRUCT_DEF_HDR_TYPE n;
   } struct_def[] =
   {
      "STRUCTURE DEFN.", 5 , "",
      "element name"   , "", TEXT_VALUE_CODE , 20, "",
      "units"          , "", TEXT_VALUE_CODE , 12, "",
      "value type"     , "", SHORT_VALUE_CODE,  1, "",
      "count"          , "", SHORT_VALUE_CODE,  1, "",
      "unused"         , "", LONG_VALUE_CODE ,  1, "",
      ""               , 0 , ""
   };

   static FORMAT_SPEC sd_fmt[] =
   {
      "%20s", 0, NULL,
      "%12s", 0, NULL,
      "%10d", 0, NULL,
      "%7d" , 0, NULL,
      "\n"  , 0, NULL
   };

   for (i = 0; i < struct_def->h.nelem; i++)
      *((FORMAT_SPEC **) (struct_def->e[i].format_ptr)) = &sd_fmt[i];
   printf("\n\n ENTER STRUCTURE NAME ==> ");
   gets(struct_name);
   struct_name[19] = '\0';
   while (struct_name[0])
   {
      if (!db->block_strdef_loaded)
         load_block_strdef();
      if ((str_def = find_def(struct_name, db->struct_def)) == NULL)
         printf("\n *** STRUCTURE DEFINITION NOT PRESENT ***\n");
      else
      {
         clear_screen();
         nelem = (unsigned int) str_def->nelem;
         printf("\nSTRUCTURE: %s      NO. OF ELEMENTS: %d\n",
            str_def->name, nelem);
         printf("\nelement           name       units      v_ty  count");
         printf("\n---------------------------------------------------\n");
         check_screen_lines(5);
         for (i = 0; i < nelem; i++)
         {
            printf("%2d", i+1);
            str_def += 1;
            print_structure(stdout, (char *) str_def, "STRUCTURE DEFN.", nelem,
               (STRUCT_DEF_HDR_TYPE *) struct_def);
            check_screen_lines(1);
         }
         printf("---------------------------------------------------\n");
      }
      printf("\n ENTER STRUCTURE NAME (<return> to quit) ==> ");
      gets(struct_name);
      struct_name[19] = '\0';
   }

   /* JR- 95/07: unnecessary & troublesome freeing & realloc/reloading--
                 memory gets fragmented when alternated with DBGET's alloc;
                 just wait till current block is closed (release_block)
   if (db->block_strdef_loaded)
   {
      free(db->block_strdef);
      db->block_strdef_loaded = 0;
   } */
}

/*-----------------------------------------------------------------------------

   FUNCTION:  shbd

      It shows the block directory.

   RETURNS:  VOID

*/
#if PROTOTYPE_ALLOWED
void shbd(void)
#else
void shbd()
#endif
{
   int oldind, i;

   oldind = db->block_dir_index;
   printf("\n\n BLOCK DIRECTORY   NENTRIES:  %d",
      db->block_dir_hdr.dir_nentries);
   printf("\n\n ENTER ENTRY NUMBER (<return> to quit) ---> ");
   gets(buff);
   while (buff[0])
   {
      if (sscanf(buff, " %d", &i) &&
         (i >= 0) && (i < db->block_dir_hdr.dir_nentries))
      {
         db->block_dir_index = i;
         load_block_dir_entry();
         shbde();
      }
      printf("\n\n ENTER ENTRY NUMBER (<return> to quit) ---> ");
      gets(buff);
   }
   db->block_dir_index = oldind;
   load_block_dir_entry();
}

/*-----------------------------------------------------------------------------

   FUNCTION:  shpd

      It shows the profile directory.

   RETURNS:  VOID

*/
#if PROTOTYPE_ALLOWED
void shpd(void)
#else
void shpd()
#endif
{
   int oldind, i;

   oldind = db->profile_dir_index;
   printf("\n\n PROFILE DIRECTORY   NENTRIES:  %d",
      db->block_hdr.dir_nentries);
   printf("\n\n ENTER ENTRY NUMBER (<return> to quit) ---> ");
   gets(buff);
   while (buff[0])
   {
      if (sscanf(buff, "%d", &i) &&
         (i >= 0) && (i < db->block_hdr.dir_nentries))
      {
         db->profile_dir_index = i;
         load_profile_dir_entry();
         shpde();
      }
      printf("\n\n ENTER ENTRY NUMBER (<return> to quit) ---> ");
      gets(buff);
   }
   db->profile_dir_index = oldind;
   load_profile_dir_entry();
}

/*-----------------------------------------------------------------------------

   FUNCTION:  shst

      It shows the database status.

   RETURNS:  VOID


void shst()
{
   printf("\n           DATABASE STATUS");
   printf("\n           ===============");
   printf("\n BLOCK DIR FILE: %s  FP: %d", db->block_dir_file, db->fpblkdir);
   printf("\n     BLOCK FILE: %s  FP: %d", db->block_file, db->fpblkdata);
   printf("\n  PRODUCER FILE: %s  FP: %d", db->producer_def_file, db->fpprddef);

   printf("\n DB IS OPEN ------------> %d", db->db_is_open);
   printf("\n BLOCK DIR IS OPEN -----> %d", db->block_dir_is_open);
   printf("\n BLOCK IS OPEN ---------> %d", db->block_is_open);
   printf("\n PROFILE IS OPEN -------> %d", db->profile_is_open);
   printf("\n NEW BLOCK IS OPEN -----> %d", db->new_block_is_open);
   printf("\n NEW PROFILE IS OPEN ---> %d", db->new_profile_is_open);
   printf("\n ACCESS MODE -----------> %d", db->access_mode);
   printf("\n CREATE MODE -----------> %d", db->create_mode);
   printf("\n MEMORY DIRECTORY ------> %d", db->memory_directory);
   printf("\n BLOCK DIR LOADED ------> %d", db->block_dir_loaded);
   printf("\n PROFILE DIR LOADED ----> %d", db->profile_dir_loaded);
   printf("\n DATA LIST LOADED ------> %d", db->data_list_loaded);
   printf("\n PRODUCER LOADED -------> %d", db->producer_loaded);
   printf("\n BLOCK DIR INDEX -------> %d", db->block_dir_index);
   printf("\n PROFILE DIR INDEX -----> %d", db->profile_dir_index);
   printf("\n BLOCK BASE TIME -------> ");
   print_ymdhms_time(stdout, &(db->block_base_time));
   printf("\n ERROR CODE: %d   ERROR DATA: %d", db->error_code, db->error_data);

}
*/
/*-----------------------------------------------------------------------------

   FUNCTION: shdata

      It shows profile data.

   RETURNS:  VOID

*/
#if PROTOTYPE_ALLOWED
void shdata(int iansw)
#else
void shdata(iansw)
int iansw;
#endif
{
   char *data;
   int type, nsteps, ierr, quit = 0;
   unsigned int nv, nb;
   YMDHMS_TIME_TYPE t;
   DMSH_POSITION_TYPE pos[2];

   do
   {
      nb = 0;
      DBGET(&iansw, NULL, &nb, &ierr);   /* find no. of bytes needed */
      if (ierr == INVALID_TYPE_REQUEST)
      {
         puts("\n\n *** VARIABLE NOT PRESENT ***");
         puts("\n\n ---Press enter to continue.---");
         getchar();
         return;
      }
      if (DBERROR(&ierr, "DBGET")) goto error_found;
/*
 --->  ALLOCATE SPACE NEEDED TO HOLD PROFILE DATA
*/
      if (nb <= 0)
      {
         printf("\n *** ZERO BYTES ***\n");
         goto error_found;
      }
      if ((data = calloc(nb, 1)) == NULL)
      {
         printf("\n *** INSUFFICIENT MEMORY ***\n");
         goto error_found;
      }
      DBGET(&iansw, data, &nb, &ierr);
      if (DBERROR(&ierr, "getting profile data\n\n"))
      {
         free(data);
         goto error_found;
      }
      if (db->data_list[iansw].value_type == STRUCT_VALUE_CODE)
      {
         if (!db->block_strdef_loaded)
            if (load_block_strdef())
            {
               printf("\n *** ERROR: %d FROM 'load_block_strdef'\n",
                  db->error_code);
               free(data);
               goto error_found;
            }
         if (!db->formats_matched)
            if ((db->error_code = match_formats(db->block_strdef, db->format_list)) != 0)
            {
               printf("\n *** ERROR: %d FROM 'match_formats'\n",
                  db->error_code);
               free(data);
               goto error_found;
            }
         nv = -nb; /* negate byte count for structure */
      }
      else
         nv = nb / VALUE_SIZE[db->data_list[iansw].value_type];
      type = TIME;
      nb = sizeof(YMDHMS_TIME_TYPE);
      DBGET(&type, (char *) &t, &nb, &ierr);
      if (DBERROR(&ierr, "getting profile time\n\n"))
      {
         free(data);
         goto error_found;
      }
      type = POSITION;
      nb = 2 * sizeof(DMSH_POSITION_TYPE);
      DBGET(&type, (char *) pos, &nb, &ierr);
      if (DBERROR(&ierr, "getting profile position\n\n"))
      {
         free(data);
         goto error_found;
      }
      clear_screen();
      printf(" BLK: %5d           TIME: ", db->block_dir_index);
      print_ymdhms_time(stdout, &t);
      if (!(t.second & 0x8000))
         printf("   ");
      printf("        LON: ");
      print_dmsh_position(stdout, &pos[0]);
      printf("\n PRF: %5d", db->profile_dir_index);
      printf("                                               LAT: ");
      print_dmsh_position(stdout, &pos[1]);
      printf("\n----------------------------------------");
      printf("---------------------------------------\n");
      check_screen_lines(3);
      if (db->data_list[iansw].scale != 1)
         printf(" <Scale = %g>", db->data_list[iansw].scale);
      if (db->data_list[iansw].offset != 0)
         printf(" <Offset = %g>", db->data_list[iansw].offset);
      printf("\n");
      check_screen_lines(1);
      print_select(stdout, data, (STRUCT_DEF_ELEM_TYPE *) &(db->data_list[iansw]),
         nv, NULL, db->struct_def); /* use default formats & structure defn. in block file */
      free(data);

      printf("\n----------------------------------------");
      printf("---------------------------------------");
      printf("\n ENTER # OF PROFILES TO MOVE <return to quit> ===> ");
      gets(buff);
      if (sscanf(buff, "%d", &nsteps) == 1)
      {
         DBMOVE(&nsteps, &ierr);
         if (DBERROR(&ierr, "DBMOVE")) goto error_found;
      }
      else
         quit = 1;
   } while (!quit);
   /* JR- 95/07: unnecessary & troublesome freeing & realloc/reloading--
                 memory gets fragmented when alternated with DBGET's alloc
   goto free_strdef; */
   return;

   error_found:
      puts("\n ---Press enter to continue.---");
      getchar();
   /* 95/07 JR-
   free_strdef:
      if (db->block_strdef_loaded)
      {
         free(db->block_strdef);
         db->block_strdef_loaded = 0;
      } */
}

extern int max_screen_lines;

/*-----------------------------------------------------------------------------

    FUNCTION:  set_max_screen_lines

       Resets the global variable max_screen_lines.

    PARAMETER:  n = new maximum

*/
#if PROTOTYPE_ALLOWED
void set_max_screen_lines(int n)
#else
void set_max_screen_lines(n)
int n;
#endif
{
   if (n > 0) max_screen_lines = n;
   /* 1999/07/14 Pierre Jaccard
      Implementing a compile time option for the screen size.

      Old code:
      else max_screen_lines = 20;
   
      New code:
   */
   else{
#ifndef DEFAULT_SCREEN_SIZE 
#   define DEFAULT_SCREEN_SIZE 20
#endif
     max_screen_lines = DEFAULT_SCREEN_SIZE ; /* reset to default */
   }
}

