/*  misc.cpp
    small helper functions that don't fit anywhere else
  
    24.04.2000: tk, initial implementation.

    Copyright (c)2000 by Thomas Kindler, thomas.kindler@gmx.de

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
    published by the Free Software Foundation; either version 2 of
    the License, or (at your option) any later version. Read the
    full License at http://www.gnu.org/copyleft for more details.
*/

// include files -----
//
#include <stdlib.h> 
#include <io.h>
#include <dos.h>
#include <math.h>
#include <stdio.h>
#include <assert.h>
#include <ctype.h>
#include "misc.h"

/**
 * Generate a text-mode progress bar.
 *
 * \param  v       current value
 * \param  min     minimum value
 * \param  max     maximum value
 */
char *ProgressBar(float v, float min, float max)
{
  static char *wheel = "|/-\\";
  static int  spin;
  static char buf[32];

  float  progress = ((v-min)/(max-min));
  if (progress<0) progress = 0;
  if (progress>1) progress = 1;

  assert(
    sprintf( buf, "---------- %2.0f%% %c",
             progress*100, wheel[spin++ % sizeof(wheel)] )
    < sizeof(buf)
  );

  for (int i=0; i<floor(progress*10); i++)
    buf[i] = '=';

  return buf;
}


/**
 * Generates a nice hexdump of a memory area.
 * This function is most useful for debugging.
 *
 * \param  mem    pointer to memory to dump
 * \param  length how many bytes to dump
 */
void HexDump(void *mem, unsigned length)
{
  char  line[80];
  char  huge *src = (char*)mem;

  printf("\ndumping %u bytes from %p\n", length, src);
  printf("       0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F"
         "    0123456789ABCDEF\n");
  for (unsigned i=0; i<length; i+=16, src+=16) {
    char *t = line;

    t += sprintf(t, "%04x:  ", i);
    for (int j=0; j<16; j++) {
      if (i+j < length)
        t += sprintf(t, "%02X", src[j] & 0xff);
      else
        t += sprintf(t, "  ");
      t += sprintf(t, j%2 ? " " : "-");
    }

    t += sprintf(t, "  ");
    for (int j=0; j<16; j++) {
      if (i+j < length) {
        if (isprint(src[j]))
          t += sprintf(t, "%c", src[j]);
        else
          t += sprintf(t, ".");
      } else {
          t += sprintf(t, " ");
      }
    }

    t += sprintf(t, "\n");
    printf("%s", line);
  }
}


/**
 * Load a file from disk.
 *
 * \param fn  filename to load
 * \param len pointer to variable receiving the
 *            length of the loaded file. (may be
 *            NULL)
 * \return    pointer to malloc'd memory, or NULL
 *            if some error occured.
 */
void *loadfile(char *fn, unsigned *len)
{
  void *mem = NULL;

  FILE *f = fopen(fn, "rb");
  unsigned flen = 0; 

  if (f) {
    flen = filelength(fileno(f));
    mem  = malloc(flen);
    if (mem)
      fread(mem, flen, 1, f);
    fclose(f);
  }

  if (len)
    *len = mem ? flen : 0;

  return mem;
}

