Macro_File CONVERT;
/* ******************************************************************************
                          MULTI-EDIT MACRO FILE

Name       : CONVERT

Description: This macro file contains routines to convert data into
             other quantities, like hex to dec, etc.

Param      : String "startradix:number:endradix"
             If not set then read from textwindow

ToDo       : CONVERTBASE  - Change value string into new radix

Problems   :

10-Nov-2009  Solved: When converting the number string is 0 then the result string
             was empty. This was true for $0 #0 as with the explicit radix
             conversion definition like 16:0:10, the original value string is
             returned as result.
             Solved: Call of ConvertBase now also possible from other macro's
             added str parameter and str result (#include Convert.sh). Also
             works on string under cusor when no paramater is given to the
             function|macro call

10-Feb-2006
Wrote this for ME6 and tested it on MEW2006. still working

                    (C) Copyright 1997 by Lars Van Jeurissen
****************************************************************************** */

#include Convert.sh



str ConvertBase ( str radixStr ) TRANS
/*******************************************************************************
                                MULTI-EDIT MACRO

Name: CONVERTBASE

Description:  Convert number under cursor to base specified in string
              under the cursor in the folowing way:

              10:1200:16
              2:10110:10
              ³   ³   ³
              ³   ³   ³
              ³   ³   ³
              ³   ³   ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ endbase  2 .. 32
              ³   ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ number to convert
              ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ startbase 2 .. 32

              first example converts a decimal number to hexadecimal
              old string will be replaced by 4B0
              second example converts a binair number to decimal
              old string will be replaced by 22

ToDo:         Searching for a convenient method to pass on the starting
              base and base we want to convert to!

Date:         Sunday 16-01-94 20:45 by LVJ started with radix.s
              Friday 21-01-94 02:15 by LVJ added $ # % & H 0x recognition

*******************************************************************************/
{
 str number_str[50] = "",
     start_base_str[10] = "",
     end_base_str[10] = "",
     conv_number_str[30] = "",
     converted_str[30] = "",
     part_str[5] = "",
     old_word_delimits[50] = word_delimits,
     ret_str = "";
 int numberrecognition = false,
     startbase = 0,
     endbase = 0,
     strlen = 0,
     temp = 0,
     startnum = 0,
     fpos1 = 0,
     fpos2 = 0,
     i = 0;

    if (radixStr == "") {
      /* It is not necesarry to place cursor at begin of word, we wil get
         begin of word ourself */
      if ((cur_char == " ")) {
        /* We Don't stand on a word */
          rm("meerror^messageBox /M=No word under cursor.");
          goto exit;
      }

      /* To begin of number under cursor (use delimiters) */
      /* 16:1A1B1:24  */
      word_delimits = " ";

      right;
      word_left;

      /* Get total number string xx:xxx:xx or other format like $... */

      number_str = Get_Word(" ");
    }
    else {
      number_str = radixStr;
    }

    /* recognition parsing ... $... #... &...  %... 0x.... on number_str */
    part_str = str_char(number_str,1);

    /* hexadecimal 1 */
    if (part_str == "$") {
      conv_number_str = copy(number_str,2,length(number_str));
      start_base_str = "16";
      end_base_str = "10";
      numberrecognition = true;
    }

    /* decimal */
    if (part_str == "#") {
      conv_number_str = copy(number_str,2,length(number_str));
      start_base_str = "10";
      end_base_str = "16";
      numberrecognition = true;
    }

    /* octal */
    if (part_str == "&") {
      conv_number_str = copy(number_str,2,length(number_str));
      start_base_str = "8";
      end_base_str = "10";
      numberrecognition = true;
    }

    /* binair */
    if (part_str == "%") {
      conv_number_str = copy(number_str,2,length(number_str));
      start_base_str = "2";
      end_base_str = "10";
      numberrecognition = true;
    }

    /* hexadecimal 2 */
    if (part_str == "0") {
      part_str = part_str + caps(str_char(number_str,2));
      if (part_str == "0X") {
        conv_number_str = copy(number_str,3,length(number_str));
        start_base_str = "16";
        end_base_str = "10";
        numberrecognition = true;
      }
    }

    /* did we find a base recognition like $ # etc. else check for ...H */
    /* recognition parsing ...H ...h on number_str */
    if (numberrecognition == false) {
      part_str = caps(str_char(number_str,length(number_str)));
      if (part_str == "H") {
        conv_number_str = copy(number_str,1,length(number_str) - 1);
        start_base_str = "16";
        end_base_str = "10";
        numberrecognition = true;
      }
    }

    /* Did we find a base yet */
    /* Parse number_str xx:xxx:xx */
    if (numberrecognition == false) {
      fpos1 = xpos(":",number_str,1);
      fpos2 = xpos(":",number_str,fpos1+1);
      if ((fpos1 == 0)||(fpos2 == 0)) {
        rm("meerror^messageBox /M=startbase or endbase not found!");
        goto exit;
      } else {
        start_base_str = copy(number_str, 1, fpos1-1);
        conv_number_str = copy(number_str,fpos1+1,fpos2-fpos1-1);
        end_base_str = copy(number_str,fpos2+1,length(number_str)-fpos2);
      }
    }

    /* check if we have the proper strings to convert */
    make_message("StartBase: "+start_base_str+" Number: "+conv_number_str+" EndBase: "+end_base_str);

    if ((start_base_str == "")||(end_base_str == "")||(conv_number_str == "")) {
      rm("meerror^messageBox /M=Could not parse the proper values to convert");
      goto exit;
    }

    /* Convert startbase and Endbase to numeric values */
    if (val(startbase,start_base_str) != 0) {
      rm("meerror^messageBox /M="+start_base_str+" is no good!");
      goto exit;
    }
    if (val(endbase,end_base_str) != 0) {
      rm("meerror^messageBox /M="+end_base_str+" is no good!");
      goto exit;
    }
    if ((startbase < 2) || (startbase > 36)) {
      rm("meerror^messageBox /M=StartBase "+Str(startbase)+" not among 2 and 36 !");
      goto exit;
    }
    if ((endbase < 2) || (endbase > 36)) {
      rm("meerror^messageBox /M=StartBase "+Str(endbase)+" not among 2 and 36 !");
      goto exit;
    }

    conv_number_str = caps(conv_number_str);
    strlen = length(conv_number_str);

    /* Check if we have a zero value string */
    if (Val(startnum, conv_number_str) == 0) {
      if ( startnum == 0 ) {
        converted_str = conv_number_str;
        startnum = 0;
        goto convert_done;
      }
    }


    /* Now start converting the string */
    startnum = 0;

    for (i=1; i<=strlen; i++) {
      part_str = str_char(conv_number_str,i);
      if ((part_str >= "0") && (part_str <= "9")) {
        val(temp,part_str);
      }
      if ((part_str >= "A") && (part_str <= "Z")) {
        temp = ascii(part_str) - 48;
        if (startbase > 10) {
          temp = temp - 7;
        }
      }
      startnum = startbase * startnum + temp;
    }

    /* OK now we have a decimal in start_num ,convert it now to end_base */
    converted_str = "";

    while (startnum>0){
      temp = startnum % endbase;  /* modulus */

      if (temp<10) {
        converted_str = char(temp+48)+converted_str;
      } else {
        converted_str = char(temp+55)+converted_str;
      }

    startnum = startnum/endbase;

    }

convert_done:
    if (radixStr == "")
    {
      /* OK we now have te string we want to replace the old string with */
      word_delimits = " ";

      push_undo;

      word_left;

      rm("mesys^delword");

      if (numberrecognition == true) {
        switch(endbase) {
          case 2:  part_str = "%";
                   break;
          case 8:  part_str = "&";
                   break;
          case 10: part_str = "#";
                   break;
          case 16: part_str = "$";
                   break;
        }
      } else {
        part_str = "";
      }

      converted_str = part_str + converted_str + char(32);

      text(converted_str);

      pop_undo;

      goto exit;
    }
    else {
      if (numberrecognition == true) {
        switch(endbase) {
          case 2:  part_str = "%";
                   break;
          case 8:  part_str = "&";
                   break;
          case 10: part_str = "#";
                   break;
          case 16: part_str = "$";
                   break;
        }
      } else {
        part_str = "";
      }

      converted_str = part_str + converted_str;
      ret_str = converted_str;

      goto exit;
    }

exit:
    /* Restore old delimiters */
    word_delimits = old_word_delimits;

    // give back the string we converted
    return(ret_str);
}



macro Convert( str radixStr = Parse_Str( "/RS=", MParm_Str ) )
/*******************************************************************************
                                MULTI-EDIT MACRO

Name: CONVERT

Description:  Convert number which is given as parameter /RS=16:8000:2
              the result (1000000000000000) is inserted or overwritten at
              the cursor position, depending on INS/OVR status.

Date:         11-11-2009 16:57

*******************************************************************************/
{
  text(ConvertBase(radixStr));
}



