//  This may look like C code, but it is really -*- C++ -*-

//  ------------------------------------------------------------------
//  The Goldware Library
//  Copyright (C) 1990-1999 Odinn Sorensen
//  Copyright (C) 1999-2000 Alexander S. Aganichev
//  ------------------------------------------------------------------
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Library General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Library General Public License for more details.
//
//  You should have received a copy of the GNU Library General Public
//  License along with this program; if not, write to the Free
//  Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
//  MA 02111-1307, USA
//  ------------------------------------------------------------------
//  $Id$
//  ------------------------------------------------------------------
//  Utility functions.
//  ------------------------------------------------------------------

#include <cstdlib>
#include <gutlmisc.h>
#include <gstrall.h>


//  ------------------------------------------------------------------
//  Get yes/no value

int GetYesno(const char* value) {

  if(isdigit(*value))
    return atoi(value);

  switch(g_toupper(*value)) {

    case NUL:   // Blank
    case 'T':   // True
    case 'Y':   // Yes
      return YES;

    case 'F':   // False
    case 'N':   // No
      return NO;

    case 'O':   // On or Off
      if(g_toupper(value[1]) == 'N')
        return YES;
      else
        return NO;

    case 'A':   // Always, Ask or Auto
      if(g_toupper(value[1]) == 'L')
        return ALWAYS;
      else if(g_toupper(value[1]) == 'S')
        return ASK;
      else
        return GAUTO;

    case 'M':   // Maybe
      return MAYBE;
  }

  return NO;
}


//  ------------------------------------------------------------------
//  Calculates a percentage

int Pct(uint32_t x, uint32_t y) {

  if(x) {

    uint32_t p = (((x-y)*100)/x);
    uint32_t r = (((x-y)*100)%x);

    if(((r*10)/x)>4)
      p++;

    return (int)p;
  }

  return 100;
}


//  ------------------------------------------------------------------
//  Calculates next tab stop from given column

int tabstop(int column, int tabwidth) {

  int sum = column + tabwidth;
  return sum - (sum % tabwidth);
}


//  ------------------------------------------------------------------
//  Convert hex string to integer

uint32_t atoulx(const char* s) {

  uint32_t retval = 0;

  s = strskip_wht(s);

  while(isxdigit(*s)) {
    retval <<= 4;
    retval |= xtoi(*s);
    s++;
  }

  return retval;
}


//  ------------------------------------------------------------------

char* ltob(char* dst, uint32_t value, int fill) {

  char* p = dst;

  for(int b=1,g=0; b<33; b++) {
    if(value & 0x80000000L) {
      g = 1;
      *p++ = '1';
    }
    else {
      if(g or (b >= fill))
        *p++ = '0';
    }
    value <<= 1;
  }
  *p = NUL;

  return dst;
}


// ------------------------------------------------------------------

dword B2L(dword b) {

  byte* bp = (byte*)&b;
  return ((*bp + ((dword)bp[1] << 8) + ((dword)bp[2] << 16)) | 0x800000L) >> (24 - (bp[3] - 0x80));
}


// ------------------------------------------------------------------

dword L2B(dword l) {

  // Special case for zero
  if(l == 0)
    return 0;

  // Look for the largest power of 2
  int s = 31;
  dword p = 0x80000000UL;
  while(s > 0) {
    if(p & l)
      break;
    p >>= 1;
    s--;
  }

  // Fillup the mantisse with useful information
  dword b = 0;
  int n = 0;
  int e = s--;
  l -= 1UL << e;
  while(l > 0) {
    dword t = (1UL << s);
    if(l >= t) {
      b += 1UL << (22 - n);
      if(l < t)
        break;
      l -= t;
    }
    n++;
    s--;
  }

  return b | ((0x81UL+e) << 24);
}


//  ------------------------------------------------------------------