Numeric base translator

Ask questions about how to create a script or swap scripts with other users.
Post Reply
jgodfrey
Posts: 471
Joined: 19 Aug 2011 23:02
Location: Missouri, USA

Numeric base translator

Post by jgodfrey »

I've always liked the built-in numeric base translator in PSPad. It has a number of advantages over TextEd's "Convert" utility when all you need is a quick base conversion (and want to cut/paste the result). So, I set out to (somewhat) replicate it in a TextEd script. While the below script doesn't handle as many conversions as the PSPad version, it does what I typically need (decimal, hex, and binary). I may add some additional number bases to it at some point, but for now, it'll suffice:

One word of caution... At some point, when the converted values get (really) huge, some numerical inaccuracy seems to creep into the conversion algorithm. However, since that point is far beyond any legitimate value I'd need to convert, I haven't (and probably won't) dig into it...

**** Edited to work with RJTE 8.95 or greater (JAG, 09-Apr-2014) ****

Code: Select all

#language C++Script

// BaseTranslator.cpp

// Jeff Godfrey, 05-Sep-2011

// Converts values between Decimal, Hex, and Binary

// Base conversion algorithm from:
// http://www.oocities.org/athens/acropolis/2692/computer/numericbase.html

TForm frmMain;
TButton btnOK;
TLabel lblDecimal; TEdit entDecimal;
TLabel lblHex; TEdit entHex;
TLabel lblBinary; TEdit entBinary;

string charList = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

void BuildUI()
{
   int col1 = 10;
   int col2 = 85;
   int rowSpace = 27;
   int top = 12;
   int frmWidth = 450;
   int frmHeight = 175;
   int entWidth = frmWidth - 150;

   frmMain = new TForm(nil);
   frmMain.Caption = "Numeric Base Translator";
   frmMain.BorderStyle = bsDialog;
   frmMain.Position = poScreenCenter;
   frmMain.Width = frmWidth;
   frmMain.Height = frmHeight;

   lblDecimal = new TLabel(frmMain);
   lblDecimal.Parent = frmMain;
   lblDecimal.Left = col1;
   lblDecimal.Top = top;
   lblDecimal.Caption = "Decimal:";

   entDecimal = new TEdit(frmMain);
   entDecimal.Name = "decimal";
   entDecimal.Text = "";
   entDecimal.Parent = frmMain;
   entDecimal.Width = entWidth;
   entDecimal.Left = col2;
   entDecimal.Top = top - 4;
   entDecimal.OnKeyPress = &KeyPress;
   entDecimal.OnKeyUp = &UpdateAll;

   top += rowSpace;

   lblHex = new TLabel(frmMain);
   lblHex.Parent = frmMain;
   lblHex.Left = col1;
   lblHex.Top = top;
   lblHex.Caption = "HexaDecimal:";

   entHex = new TEdit(frmMain);
   entHex.Name = "hex";
   entHex.Text = "";
   entHex.Parent = frmMain;
   entHex.Width = entWidth;
   entHex.Left = col2;
   entHex.Top = top - 4;
   entHex.OnKeyPress = &KeyPress;
   entHex.OnKeyUp = &UpdateAll;

   top += rowSpace;

   lblBinary = new TLabel(frmMain);
   lblBinary.Parent = frmMain;
   lblBinary.Left = col1;
   lblBinary.Top = top;
   lblBinary.Caption = "Binary:";

   entBinary = new TEdit(frmMain);
   entBinary.Name = "binary";
   entBinary.Text = "";
   entBinary.Parent = frmMain;
   entBinary.Width = entWidth;
   entBinary.Left = col2;
   entBinary.Top = top - 4;
   entBinary.OnKeyPress = &KeyPress;
   entBinary.OnKeyUp = &UpdateAll;

   btnOK = new TButton(frmMain);
   btnOK.Parent = frmMain;
   btnOK.Width = 80;
   btnOK.Left = frmWidth - btnOK.Width - 15;
   btnOK.Top = frmHeight - 60;
   btnOK.Caption = "OK";
   btnOK.OnClick = &ButtonClick;
}

void ButtonClick(TButton Sender)
{
   frmMain.ModalResult = mrOK;
}

void KeyPress(TObject sender, int key)
{
   int base = 10;
   string name = TEdit(sender).Name;
   if (name == "decimal")     { base = 10; }
   else if (name == "hex")    { base = 16; }
   else if (name == "binary") { base = 2; }
   else { ShowMessage("Unknown control -> " + name); }
   string validKeys = Copy(charList, 1, base);
   //int val = Ord(key);
   if ((key != 8) && (ScriptUtils.WPosFrom(Chr(key), validKeys, 1) == 0)) { key = 0; }
}

void UpdateAll(TObject sender, char key)
{
   try
   {
      string name = TEdit(sender).Name;
      if (name == "decimal")
      {
         entBinary.Text = Base2Base(entDecimal.Text, 10, 2);
         entHex.Text = Base2Base(entDecimal.Text, 10, 16);
      }
      else if (name == "hex")
      {
         entDecimal.Text = Base2Base(entHex.Text, 16, 10);
         entBinary.Text = Base2Base(entHex.Text, 16, 2);
      }
      else if (name == "binary")
      {
         entDecimal.Text = Base2Base(entBinary.Text, 2, 10);
         entHex.Text = Base2Base(entBinary.Text, 2, 16);
      }
      else
      {
         ShowMessage("Unknown control -> " + name);
      }
   }
   except
   {
      ShowMessage("Unable to convert specified value!");
      clearAll();
   }
}

string Base2Base(string inString, int baseIn, int baseOut)
{
   int maxBase = Length(charList);
   if ((baseIn > maxBase) || (baseOut > maxBase))
   {
      return "N/A";
   }

   if (inString == "0") { return "0"; }

   string outputVal = "";

   try
   {

      // Convert the passed numeric string to a base 10 number
      int inputLength = Length(inString);
      int decimalVal = 0;
      for (int j = 1; j <= inputLength; j++)
      {
         for (int k = 1; k <= baseIn; k++)
         {
            if (Copy(inString, j, 1) == Copy(charList, k, 1))
            {
               decimalVal = decimalVal + int((k - 1) * Power(baseIn, (inputLength - j)) + 0.5);
            }
         }
      }

      // Convert the base 10 value to the required output base
      while (decimalVal > 0)
      {
         int x = int((((decimalVal/baseOut) - int(decimalVal/baseOut)) * baseOut) + 1.5);
         outputVal = Copy(charList, x, 1) + outputVal;
         decimalVal = int(decimalVal/baseOut);
      }
   }
   finally
   {
      if ((Length(inString) > 0) && (Length(outputVal) == 0)) { outputVal = "ERROR"; }
      return outputVal;
   }
}

void ClearAll()
{
   entDecimal.Text = "";
   entHex.Text = "";
   entBinary.Text = "";
}

// Raises x to the power of y
float Power(float x, float y)
{
   return Exp(y * Ln(x));
}

{
   BuildUI();
   frmMain.ShowModal;
   frmMain.Free;
}
Last edited by jgodfrey on 09 Apr 2014 16:28, edited 2 times in total.

jgodfrey
Posts: 471
Joined: 19 Aug 2011 23:02
Location: Missouri, USA

Re: Numeric base translator

Post by jgodfrey »

I just upgraded to 8.91 and now my "Numeric base translator" script (see OP) no longer works. I realize the scripting engine has undergone some large updates that have likely caused this.

Anyway, when I run it now, I simply get a dialog stating "Incompatible types: 'Char', 'Integer'"

I spent a few minutes making obvious changes based on the mentioned scripting engine updates but never found the actual problem. I decided it might be quickest to just ask Rickard for some advice.

Thanks for any input.

Jeff

User avatar
Rickard Johansson
Site Admin
Posts: 6001
Joined: 19 Jul 2006 14:29

Re: Numeric base translator

Post by Rickard Johansson »

Made some minor changes. It still doesn't work properly yet. The editor component (TEdit) use ANSI while the script engine use Unicode. I need to replace all the components for events like

entDecimal.OnKeyPress = &KeyPress;

to work. I had to comment out some events for the script to work below.

Code: Select all

#language C++Script

// BaseTranslator.cpp

// Jeff Godfrey, 05-Sep-2011

// Converts values between Decimal, Hex, and Binary

// Base conversion algorithm from:
// http://www.oocities.org/athens/acropolis/2692/computer/numericbase.html

TForm frmMain;
TButton btnOK;
TLabel lblDecimal; TEdit entDecimal;
TLabel lblHex; TEdit entHex;
TLabel lblBinary; TEdit entBinary;

string charList = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

void BuildUI()
{
   int col1 = 10;
   int col2 = 85;
   int rowSpace = 27;
   int top = 12;
   int frmWidth = 450;
   int frmHeight = 175;
   int entWidth = frmWidth - 150;

   frmMain = new TForm(nil);
   frmMain.Caption = "Numeric Base Translator";
   frmMain.BorderStyle = bsDialog;
   frmMain.Position = poScreenCenter;
   frmMain.Width = frmWidth;
   frmMain.Height = frmHeight;

   lblDecimal = new TLabel(frmMain);
   lblDecimal.Parent = frmMain;
   lblDecimal.Left = col1;
   lblDecimal.Top = top;
   lblDecimal.Caption = "Decimal:";

   entDecimal = new TEdit(frmMain);
   entDecimal.Name = "decimal";
   entDecimal.Text = "";
   entDecimal.Parent = frmMain;
   entDecimal.Width = entWidth;
   entDecimal.Left = col2;
   entDecimal.Top = top - 4;
   // entDecimal.OnKeyPress = &KeyPress;
   entDecimal.OnKeyUp = &UpdateAll;

   top += rowSpace;

   lblHex = new TLabel(frmMain);
   lblHex.Parent = frmMain;
   lblHex.Left = col1;
   lblHex.Top = top;
   lblHex.Caption = "HexaDecimal:";

   entHex = new TEdit(frmMain);
   entHex.Name = "hex";
   entHex.Text = "";
   entHex.Parent = frmMain;
   entHex.Width = entWidth;
   entHex.Left = col2;
   entHex.Top = top - 4;
   // entHex.OnKeyPress = &KeyPress;
   entHex.OnKeyUp = &UpdateAll;

   top += rowSpace;

   lblBinary = new TLabel(frmMain);
   lblBinary.Parent = frmMain;
   lblBinary.Left = col1;
   lblBinary.Top = top;
   lblBinary.Caption = "Binary:";

   entBinary = new TEdit(frmMain);
   entBinary.Name = "binary";
   entBinary.Text = "";
   entBinary.Parent = frmMain;
   entBinary.Width = entWidth;
   entBinary.Left = col2;
   entBinary.Top = top - 4;
   // entBinary.OnKeyPress = &KeyPress;
   entBinary.OnKeyUp = &UpdateAll;

   btnOK = new TButton(frmMain);
   btnOK.Parent = frmMain;
   btnOK.Width = 80;
   btnOK.Left = frmWidth - btnOK.Width - 15;
   btnOK.Top = frmHeight - 60;
   btnOK.Caption = "OK";
   btnOK.OnClick = &ButtonClick;
}

void ButtonClick(TButton Sender)
{
   frmMain.ModalResult = mrOK;
}

void KeyPress(TObject sender, char key)
{
   int base = 10;
   string name = TEdit(sender).Name;
   if (name == "decimal")     { base = 10; }
   else if (name == "hex")    { base = 16; }
   else if (name == "binary") { base = 2; }
   else { ShowMessage("Unknown control -> " + name); }
   string validKeys = Copy(charList, 1, base);
   int val = StrToInt(key);
   if ((val != 8) && (ScriptUtils.PosFrom(key, validKeys, 1) == 0)) { key = chr(0); }
}

void UpdateAll(TObject sender, char key)
{
   try
   {
      string name = TEdit(sender).Name;
      if (name == "decimal")
      {
         entBinary.Text = Base2Base(entDecimal.Text, 10, 2);
         entHex.Text = Base2Base(entDecimal.Text, 10, 16);
      }
      else if (name == "hex")
      {
         entDecimal.Text = Base2Base(entHex.Text, 16, 10);
         entBinary.Text = Base2Base(entHex.Text, 16, 2);
      }
      else if (name == "binary")
      {
         entDecimal.Text = Base2Base(entBinary.Text, 2, 10);
         entHex.Text = Base2Base(entBinary.Text, 2, 16);
      }
      else
      {
         ShowMessage("Unknown control -> " + name);
      }
   }
   except
   {
      ShowMessage("Unable to convert specified value!");
      clearAll();
   }
}

string Base2Base(string inString, int baseIn, int baseOut)
{
   int maxBase = Length(charList);
   if ((baseIn > maxBase) || (baseOut > maxBase))
   {
      return "N/A";
   }

   if (inString == "0") { return "0"; }

   string outputVal = "";

   try
   {

      // Convert the passed numeric string to a base 10 number
      int inputLength = Length(inString);
      int decimalVal = 0;
      for (int j = 1; j <= inputLength; j++)
      {
         for (int k = 1; k <= baseIn; k++)
         {
            if (Copy(inString, j, 1) == Copy(charList, k, 1))
            {
               decimalVal = decimalVal + int((k - 1) * Power(baseIn, (inputLength - j)) + 0.5);
            }
         }
      }

      // Convert the base 10 value to the required output base
      while (decimalVal > 0)
      {
         int x = int((((decimalVal/baseOut) - int(decimalVal/baseOut)) * baseOut) + 1.5);
         outputVal = Copy(charList, x, 1) + outputVal;
         decimalVal = int(decimalVal/baseOut);
      }
   }
   finally
   {
      if ((Length(inString) > 0) && (Length(outputVal) == 0)) { outputVal = "ERROR"; }
      return outputVal;
   }
}

void ClearAll()
{
   entDecimal.Text = "";
   entHex.Text = "";
   entBinary.Text = "";
}

// Raises x to the power of y
float Power(float x, float y)
{
   return Exp(y * Ln(x));
}

{
   BuildUI();
   frmMain.ShowModal;
   frmMain.Free;
}

User avatar
Rickard Johansson
Site Admin
Posts: 6001
Joined: 19 Jul 2006 14:29

Re: Numeric base translator

Post by Rickard Johansson »

I implemented a different solution. Instead of replacing all components I simply made some changes to the event handlers.

E.g.

void KeyPress(TObject sender, char key) => void KeyPress(TObject sender, int key)

Code: Select all

void KeyPress(TObject sender, int key)
{
   int base = 10;
   string name = TEdit(sender).Name;
   if (name == "decimal")     { base = 10; }
   else if (name == "hex")    { base = 16; }
   else if (name == "binary") { base = 2; }
   else { ShowMessage("Unknown control -> " + name); }
   string validKeys = Copy(charList, 1, base);
   if ((key != 8) && (ScriptUtils.PosFrom(Chr(key), validKeys, 1) == 0)) { key = 0; }
}
I'll release an update in a few days.

jgodfrey
Posts: 471
Joined: 19 Aug 2011 23:02
Location: Missouri, USA

Re: Numeric base translator

Post by jgodfrey »

Rickard Johansson wrote:I'll release an update in a few days.
Thanks Rickard - no rush.

Jeff

jgodfrey
Posts: 471
Joined: 19 Aug 2011 23:02
Location: Missouri, USA

Re: Numeric base translator

Post by jgodfrey »

Based on Rickard's above input, I've edited the original script (posted at the top of this thread) to be compatible with RJTE 8.95 or greater.

Jeff

Post Reply