Boxer's macro language has been used to solve a wide array of problems for our customers since its debut in v10. Below are some macros that were sent in by customers — or developed here in-house — that help illustrate the use of the language. You may find a macro to solve a problem you've been having, or get an idea for a new macro based on these samples.

How to use these macros: You can select the text of a macro and copy it to the clipboard, or use the link provided to download the macro as a file. To make a macro visible within the Tools|Run Macro menu, simply place the file in Boxer's "Macros" subdirectory. Note: if clicking the download link displays the macro on a new page, rather than opening a download dialog, right click on that link and use the "Save Target As" option. Or, if you'd like to get all the macros, download this zip file that contains all the sample macros listed below.

List of Macros
Move cursor to bottom of paragraph
Move cursor to top of previous paragraph
Move cursor to top of current paragraph
Move cursor to top of next paragraph
Add a newline after every closing angle bracket
Apply HTML markup to a simple text file
Display an ASCII chart in a new file
Convert comma-separated-value (CSV) data
Cut lines containing a user-defined string
Delete blank lines
Delete lines containing a user-defined string
Delete lines NOT containing a user-defined string
Compute return on a deposited amount
Add blank lines after lines ending with !.?
Double space and reformat
Extract email addresses
Hex to Decimal
Obfuscate selected text with HTML codes
Display 24-hour time
Reduce blank lines
Reformat to alternate text width
Extract double quoted strings
Reverse the text of each line
Reverse names: Smith.Bob to Bob.Smith
Truncate lines after a user-defined string
Truncate lines at a user-defined string
Delete lines that begin with a user-defined string
Delete lines that end with a user-defined string
Call MapQuest to show a map
Convert British English punctuation to American English punctuation
Convert small GIFs to BASE64 for use in Mozilla URLs
 

Move cursor to bottom of paragraph   (download BottomOfParagraph.bm)
// move the cursor to the bottom line of the current paragraph

macro BottomOfParagraph()
{
while (LineNumber < LineCount && !LineIsEmpty(LineNumber+1))
    Down;
}
 

Move cursor to top of previous paragraph   (download TopOfPreviousParagraph.bm)
// move the cursor to the top line of the previous paragraph

macro TopOfPreviousParagraph()
{
Up;

while (LineNumber > 1 && !LineIsEmpty(LineNumber-1))
    Up;
    
StartOfLine;
}
 

Move cursor to top of current paragraph   (download TopOfCurrentParagraph.bm)
// move the cursor to the top line of the current paragraph

macro TopOfCurrentParagraph()
{
while (LineNumber > 1 && !LineIsEmpty(LineNumber-1))
    Up;
}
 

Move cursor to top of next paragraph   (download TopOfNextParagraph.bm)
// move the cursor to the first line of the next paragraph

macro TopOfNextParagraph()
{
while (LineNumber < LineCount && !LineIsEmpty(LineNumber))
    Down;

Down;
StartOfLine;
}
 

Add a newline after every closing angle bracket   (download AddNewlineAfterCloseAngle.bm)
// add a newline after each closing angle (>) character
// unless the angle already appears at end of line

macro AddNewlineAfterCloseAngle()
{
int line, i, j;
string str;

// loop on all lines in the file
for (line = 1; line <= LineCount(); line++)
    {
    // get the text of line 'line' into string 'str'
    GetLineText(line, str);

    // get the index of the closing angle
    j = strchr(str, '>');
    
    // if the character was found and was not at end-of-line...
    if (j != -1 && str[j+1] != '\0')
        {
        GotoLine(line);
        GotoColumn(1);

        // advance the cursor to the character      
        while (ValueAtCursor() != '>')
            Right;

        // and past the character
        Right;

        // insert a newline
        Enter;

        // process this line again in case other tags exist
        line--;
        }
    }
}
 

Apply HTML markup to a simple text file   (download ApplyHTMLMarkup.bm)
// apply HTML markup to a simple text file
// also converts double quote, ampersand, and
// angle brackets to HTML equivalents

macro ApplyHTMLMarkup()
{
int prevlen, len, i;
string str;
int numchanges;

// loop on all lines in the file
for (i = 1; i <= LineCount; i++)
    {
    // get the text of line 'i' into 'str'
    GetLineText(i, str);

    // reset the change counter
    numchanges = 0;
        
    // convert sensitive characters to HTML codes
    numchanges += ChangeString(str, "&",  "&amp;");
    numchanges += ChangeString(str, "<",  "&lt;");
    numchanges += ChangeString(str, ">",  "&gt;");
    numchanges += ChangeString(str, "\"", "&quot;");

    // if changes were made, replace the line's text
    if (numchanges > 0)
        PutLineText(i, str);
    }

// move to top of file
StartOfFile;
Down;

// loop on all lines in the file, starting on line 2
for (i = 2; i <= LineCount; i++)
        {
        // get the length of the previous line
        prevlen = LineLength(i-1);

        // get the length of this line
        len = LineLength(i);

        // if this line is empty, and the previous line isn't...
        // apply <br> markers to the end of the line
        if (len == 0 && prevlen != 0)
                {
                Up;
                EndOfLine;
                PutString("<br><br>");
                StartofLine;
                Down;
                }

        Down;           // move down to the next line
        }

StartOfFile;

PutString("<html>\n");
PutString("<head>\n");
PutString("<title></title>\n");
PutString("</head>\n\n");
PutString("<body>\n");

EndOfFile;
EndOfLine;
PutString("\n");
PutString("</body>\n");
PutString("</html>\n");

// place cursor between title and /title
GotoLine(3);
GotoColumn(8);
}
 

Display an ASCII chart in a new file   (download ASCIIChart.bm)
// ASCII chart example

macro ASCIIchart(void)
{
char i;

// open a new file
New;

// loop from space to 255 to show all chars
for (i = ' '; i <= 255; i++)
    printf("The ASCII value of '%c' is %d\n", i, i);
}
 

Convert comma-separated-value (CSV) data    (download ConvertCSV.bm)
// convert comma-separated-value (CSV) data on the current
// line so that each field is placed on its own line

macro ConvertCSV()
{
string str;
int numquotes, numcommas;

// get the count of quotes/commas on this line
numquotes = LineContains(linenumber, "\"");

numcommas = LineContains(linenumber, ",");

// if this appears to be CSV data...
if (numcommas+1 == numquotes / 2)
    {
    // get the text of the current line
    GetLineText(linenumber, str);

    // remove any empty data fields
    ChangeString(str, "\"\",", ""); 

    // convert "," to a newline
    ChangeString(str, "\",\"", "\n");   

    // remove the first and last quotes
    ChangeString(str, "\"", "");    

    // select the line      
    GoToColumn(1);
    SelectToEndOfLine;
    
    // replace the selection
    PutString(str);
    }

// position for next line
Down;
StartOfLine;
}
 

Cut lines containing a user-defined string   (download CutLinesContaining.bm)

// cut lines containing a user-defined string to the Windows clipboard

macro CutLinesContaining();
{
int line;
int len;
string str;
int numcut = 0;

// get the string from the user
len = GetString("Cut lines containing this string:", str);

if (len == 0)
    return;

// make the Windows clipboard the active clipboard
SetClipboard(0);

// clear the Windows clipboard
ClearClipboard(0);

// move cursor to start of file
StartOfFile();

// loop on all lines in the file    
for (line = 1; line <= LineCount(); line++)
    {
    // does this line contain the string?
    if (LineContains(line, str))
        {
        GotoLine(line);
        CutAppend();
        numcut++;           // tally the cut
        line--;             // stay here for next line
        }
    }

// report the results
if (numcut == 1)
    message("Results", "1 line was cut to the Windows clipboard");
else
    message("Results", numcut,
                " lines were cut to the Windows clipboard");
}
 

Delete blank lines   (download DeleteBlankLines.bm)
// delete blank lines in the current file

macro DeleteBlankLines(void)
{
int i, len;

// start at the top of the file
StartOfFile;

// loop on all lines in the file
for (i = 1; i <= LineCount; i++)
    {
    // get the length of this line
    len = LineLength(i);

    // is this line empty?
    if (len == 0)
        {
        DeleteLine;     // delete this line
        i--;            // stay at this line #
        }
    else
        {
        Down;           // move down to the next line
        }
    }
}
 

Delete lines containing a user-defined string   (download DeleteLinesContaining.bm)
// deletes lines containing a user-defined string

macro DeleteLinesContaining()
{
int line;
int len;
string str;
int deleted = 0;

// get the string from the user
len = GetString("Delete lines containing this string:", str);

if (len == 0)
    return;

// loop on all lines in the file    
for (line = 1; line <= LineCount(); line++)
    {
    // does this line contain the string?
    if (LineContains(line, str))
        {
        DeleteLine(line);   // delete it
        deleted++;          // tally the deletion
        line--;             // stay here for next line
        }
    }

// report the results
if (deleted == 1)
    message("Results", "1 line was deleted");
else
    message("Results", deleted, " lines were deleted");
}
 

Delete lines NOT containing a user-defined string   (download DeleteLinesNotContaining.bm)
// deletes lines NOT containing a user-defined string

macro DeleteLinesNotContaining()
{
int line;
int len;
string str;
int deleted = 0;

// get the string from the user
len = GetString("Delete lines that do NOT contain this string:", str);

if (len == 0)
    return;

// loop on all lines in the file    
for (line = 1; line <= LineCount(); line++)
    {
    // does this line contain the string?
    if (!LineContains(line, str))
        {
        DeleteLine(line);   // delete it
        deleted++;          // tally the deletion
        line--;             // stay here for next line
        }
    }

// report the results
if (deleted == 1)
    message("Results", "1 line was deleted");
else
    message("Results", deleted, " lines were deleted");
}
 

Compute return on a deposited amount   (download ComputeDeposit.bm)
// Compute result of amount left on deposit with continuous
// compounding.  Uses the formula: P = pe^rt

macro ComputeDeposit()
{
float amt, newamt, rate, years;
string str;

GetFloat("Enter the amount on deposit:", amt);

GetFloat("Enter the interest rate:", rate);

// if user entered 5, make it .05, for example
if (rate > 1.0)
    rate /= 100.0;

GetFloat("Enter the number of years on deposit:", years);

newamt = amt * pow(e, rate * years);

sprintf(str, "The amount with interest applied is: %.2f", newamt);
Message("Result", str);
}
 

Add blank lines after lines ending with !.?   (download AddBlankLines.bm)
// add a blank line after any line that ends with !.?

macro AddBlankLines(void)
{
char ch;
int i;

// loop on all lines in the file
for (i = 1; i <= LineCount; i++)
    {
    // make sure this line is not empty
    if (LineLength(i) > 1)
        {
        // move the cursor to this line
        GotoLine(i);

        // move to the end of the line
        EndOfLine;

        // backup off newline and onto last char
        Left;

        // get the value of char at the cursor
        ch = ValueAtCursor();

        // if it's a line ender, add Enter
        if (ch == '.' || ch == '?' || ch == '!')
            {
            EndOfLine;
            Enter;
            }
        }
    }
}
 

Double space and reformat   (download DoubleSpaceAndReformat.bm)
// double space and reformat the text on the clipboard
// prepares a web document for printing

macro DoubleSpaceAndReformat(void)
{
int i;
int numlines;

// save various editor settings
SaveSettings;

// open a new file and paste from clipboard
New;
Paste;

// set Text Width to 96
TextWidth(96);

// delete all blank lines
DeleteBlankLines;

// record the number of lines BEFORE we start adding lines
numlines = LineCount - 1;

// go to the top
StartOfFile;

// double space the file
for (i = 1; i <= numlines; i++)
    {
    Down;
    PutString("\n");
    }

// reformat the whole file
SelectAllText;
Reformat;

// remove any small indents that might be present
SelectAllText;
for (i = 1; i <= 12; i++)
    Unindent;

// release the selection
Deselect;

// restore various editor settings
RestoreSettings;
}
 

Extract email addresses   (download ExtractEmailAddresses.bm)
// extract email addresses from all lines within the current file
// and append them to the end of the file

macro ExtractEmailAddresses()
{
int i, line, origlinecount;
int inword, isdelim;
int atsigns, dots;
int startword, endword;
string linetext, email;
char c;

// note the linecount before we start adding more lines
origlinecount = LineCount;

// loop on all lines in the file
for (line = 1; line <= origlinecount; line++)
    {
    // get the text of the whole line into the string 'linetext'
    GetLineText(line, linetext);

    // add a space to make end-of-line handling smoother
    strcat(linetext, " ");
    
    // loop on all characters in 'linetext'
    for (inword = FALSE, i = 0; linetext[i] != 0; i++)
        {
        c = linetext[i];

        // set a flag if this character is one that delimits words
        if (isalnum(c) || (strchr("_@.-", c) != -1))
            isdelim = FALSE;
        else
            isdelim = TRUE;

        // decide whether this character starts a new word,
        // or ends an existing word
        if (inword && isdelim)
            {
            inword = FALSE;
            endword = i-1;

            // we've just left a word: see if it had both
            // the required characters
            if (atsigns == 1 && dots >= 1)
                {
                // get the linetext address into a string
                SubString(email, linetext, startword, endword-startword+1);

                // add it to the end of the file
                EndOfFile;
                EndOfLine;
                Enter;
                PutString(email);
                }
            }
        else if (!inword && !isdelim)
            {
            inword = TRUE;
            startword = i;
            atsigns = 0;
            dots = 0;
            }

        // tally whether or not we see the required chars while we're in a 
        if (inword)
            {
            if (linetext[i] == '@')
                atsigns++;

            if (linetext[i] == '.')
                    dots++;
            }
        }
    }
}
 

Hex to Decimal   (download HexToDecimal.bm)
// shows hex to decimal conversion technique

macro HexToDecimal()
{
string str;
int x = 0;
int i, val;
char ch;

GetString("Enter a hexadecimal string", str);

for (i = 0; str[i] != '\0'; i++)
    {
    ch = str[i];

    if (!isxdigit(ch))
        {
        message("Error", "Invalid character encountered: ", ch);
        return;
        }   

    ch = toupper(ch);

    if (isalpha(ch))
        val = ch - 'A' + 10;
    else
        val = ch - '0';
        
    x = x * 16;
    x = x + val;
    }

message("Result", "The decimal value is ", x);
}
 

Obfuscate the selected text with HTML codes   (download Obfuscate.bm)
// convert the word selected into its HTML coded format

// this can be used to convert phone numbers and email addresses
// in web pages to frustrate automated crawlers from harvesting
// your information for spam lists

macro Obfuscate()
{
int i;
string str;
string result;
string tmp;

if (!TextIsSelected)
    {
    Message("Error",
      "Please select a word before\nrunning the macro.\n");
    return;
    }

GetSelection(str);

// loop on all characters in 'str'
for (i = 0; str[i] != '\0'; i++)
    {
    sprintf(tmp, "&#%03d;", str[i]);
    strcat(result, tmp);
    }

PutSelection(result);
}
 

Display 24-hour time   (download Print24HourTime.bm)
// display the current time in 24-hour time format

macro Print24HourTime()
{
int h, m, s;

GetTime24(h, m, s);
printf("%d:%02d:%02d", h, m, s);
}
 

Reduce blank lines   (download ReduceBlankLines.bm)
// reduce multiple blank lines to one blank line

macro ReduceBlankLines(void)
{
int thislen, prevlen, i;

// position cursor to line 2
StartOfFile;
Down;

// loop on all lines in the file (starting with line 2)
for (i = 2; i <= LineCount; i++)
    {
    // get the length of the previous line
    prevlen = LineLength(i-1);

    // get the length of this line
    thislen = LineLength(i);

    // are both previous and this line empty?
    if (prevlen == 0 && thislen == 0)
        {
        DeleteLine;     // delete this line
        i--;            // stay at this line #
        }
    else
        {
        Down;           // move down to the next line
        }
    }
}
 

Reformat to alternate text width   (download ReformatAlternate.bm)
// Reformat the current paragraph to 70 characters, regardless
// of what the current Text Width setting is

macro ReformatAlternate()
{
SaveSettings;
TextWidth(70);
Reformat;
RestoreSettings;
}
 

Extract double quoted strings   (download ExtractStrings.bm)
// extract double quoted strings from the current file
// and append them at the bottom of the file

macro ExtractStrings()
{
string s, s1, s2, s3;
int i, j, k;
int found = 0;
int original_linecount = LineCount();

// loop on all lines in the current file
for (i = 1; i <= original_linecount; i++)
    {
    // does this line have two or more double quotes?
    while (LineContains(i, "\"") >= 2)
        {
        // tally number of strings found
        found++;
        
        // get the text of line 'i' into string 's'
        GetLineText(i, s);

        // get the offset of the first double quote     
        j = strchr(s, '\"');

        // get the index of the second double quote
        for (k = j + 1; s[k] != '\"'; k++)
            ;

        // get the first portion into 's1'
        SubString(s1, s, 0, j);
        
        // get the second portion (the string) into 's2'
        SubString(s2, s, j, k-j+1);

        // get the third portion into 's3'
        SubString(s3, s, k+1, 2048);

        // build the new line and replace it
        s = s1;
        s += s3;
        PutLineText(i, s);
        
        // gather the strings at the bottom of the current file
        EndOfFile();
        EndOfLine();
        printf("\n%s", s2);
        }
    }

// report the results
if (found == 1)
    printf("\n\n%d string was found and removed\n", found);
else
    printf("\n\n%d strings were found and removed\n", found);
}
 

Reverse the text of each line   (download ReverseLineText.bm)
// reverse the text on every line in the file
// "abcdefg" becomes "gfedcba"

macro ReverseLineText()
{
int i, len, line;
string str;
char tmp;

// loop on all lines in the file
for (line = 1; line <= LineCount; line++)
    {
    len = linelength(line);

    // ignore lines too short/long
    if (len >= 2 && len < 2000)
        {
        // get the text of line 'line' into string 'str'
        GetLineText(line, str);

        // loop through half this line  
        for (i = 0; i < len/2; i++)
            {
            // swap the characters...
            tmp = str[i];
            str[i] = str[len-1-i];
            str[len-1-i] = tmp;
            }

        // replace line with reversed line
        PutLineText(line, str); 
        }

    }
}
 

Reverse names: Smith.Bob to Bob.Smith   (download ReverseNames.bm)
// changes a list of "Smith.Bob" entries to "Bob.Smith"

macro ReverseNames()
{
int line, i;
string str;
string first, last;
string newstring;

// loop on all lines in the file
for (line = 1; line <= LineCount; line++)
    {
    // get the text of line 'line' into string 'str'
    GetLineText(line, str);

    // look for a '.' within 'str'
    i = strstr(str, ".");
    
    if (i != -1)
        {
        // 'last' gets 'i' chars from 'str' starting at index 0
        SubString(last,  str, 0,   i);

        // 'first' gets up to 100 chars from 'str' starting at index i+1
        SubString(first, str, i+1, 100);

        // build a new string from 'first' and 'last'
        sprintf(newstring, "%s.%s", first, last);

        // replace the text of the line
        PutLineText(line, newstring);
        }
    }
}
 

Truncate lines after a user-defined string   (download TruncateLineAfterString.bm)
// truncate lines after a user-defined string

macro TruncateLineAfterString()
{
int j, line, len;
int truncated = 0;
string str, linestr, newstr;

// get the string from the user
len = GetString("Truncate lines after this string:", str);

// if the string is empty, quit
if (len == 0)
    return;

// loop on all lines in the file    
for (line = 1; line <= LineCount; line++)
    {
    GetLineText(line, linestr);
    
    // does this line contain the string?
    if ((j = strstr(linestr, str)) != -1)
        {
        // create a new string without the trailing text
        SubString(newstr, linestr, 0, j+len);

        // replace this line with the new text
        PutLineText(line, newstr);

        // tally the truncation
        truncated++;
        }
    }

// report the results
if (truncated == 1)
    message("Results", "1 line was truncated");
else
    message("Results", truncated, " lines were truncated");
}
 

Truncate lines at a user-defined string   (download TruncateLineAtString.bm)
// truncate lines at a user-defined string

macro TruncateLineAtString()
{
int j, line, len;
int truncated = 0;
string str, linestr, newstr;

// get the string from the user
len = GetString("Truncate lines at this string:", str);

// if the string is empty, quit
if (len == 0)
    return;

// loop on all lines in the file    
for (line = 1; line <= LineCount; line++)
    {
    GetLineText(line, linestr);
    
    // does this line contain the string?
    if ((j = strstr(linestr, str)) != -1)
        {
        // create a new string without the trailing text
        SubString(newstr, linestr, 0, j);

        // replace this line with the new text
        PutLineText(line, newstr);

        // tally the truncation
        truncated++;
        }
    }

// report the results
if (truncated == 1)
    message("Results", "1 line was truncated");
else
    message("Results", truncated, " lines were truncated");
}


 

Delete lines that begin with a user-defined string   (download DeleteLinesThatBeginWith.bm)
// deletes lines that begin with a user-defined string

macro DeleteLinesThatBeginWith()
{
int line, len;
string str, linestr;
int deleted = 0;

// get the string from the user
len = GetString("Delete lines that begin with:", str);

if (len == 0)
    return;

// loop on all lines in the file    
for (line = 1; line <= LineCount(); line++)
    {
    // get the text of line 'line' into 'linestr'
    GetLineText(line, linestr);
    
    // does this line start with 'str'?
    if (strncmp(linestr, str, len) == 0)
        {
        DeleteLine(line);   // delete it
        deleted++;          // tally the deletion
        line--;             // stay here for next line
        }
    }

// report the results
if (deleted == 1)
    message("Results", "1 line was deleted");
else
    message("Results", deleted, " lines were deleted");
}
 

Delete lines that end with a user-defined string   (download DeleteLinesThatEndWith.bm)
// deletes lines that end with a user-defined string

macro DeleteLinesThatEndWith()
{
int line, len, linelen;
string str, linestr, str2;
int deleted = 0;

// get the string from the user
len = GetString("Delete lines that end with:", str);

if (len == 0)
    return;

// loop on all lines in the file    
for (line = 1; line <= LineCount(); line++)
    {
    // get the text of line 'line' into 'linestr'
    linelen = GetLineText(line, linestr);

    // if the line is too short, do nothing
    if (linelen < len)
        {
        ;   
        }
    // does this line end with 'str' ?
    else
        {
        // isolate the tail of the line into a string
        SubString(str2, linestr, linelen - len, len);
        
         if (strcmp(str2, str) == 0)
            {
            DeleteLine(line);   // delete it
            deleted++;          // tally the deletion
            line--;             // stay here for next line
            }
        }
    }

// report the results
if (deleted == 1)
    message("Results", "1 line was deleted");
else
    message("Results", deleted, " lines were deleted");
}
 

Call MapQuest to show a map   (download CallMapQuest.bm)
// get an address from the user and call it up on MapQuest

macro CallMapQuest()
{
string city, state, address, country, url;
int zoom = 7;

// get information from the user
GetString("Enter street address:", address);
GetString("Enter city/town:",       city);
GetString("Enter state/province:", state);
GetString("Enter country:",         country);

// state level maps are better at zoom level 3
if (city == "")
    zoom = 3;

// country level maps are better at zoom level 1
if (state == "")
    zoom = 1;
    
// convert embedded spaces to plus signs    
ChangeString(address, " ", "+");
ChangeString(city,    " ", "+");
ChangeString(state,   " ", "+");
ChangeString(country, " ", "+");

// build the URL that will be used                          
sprintf(url,
 "http://www.mapquest.com/maps/map.adp?city=
    %s&state=%s&address=%s&country=%s&zoom=%d",
   city, state, address, country, zoom);

// send the URL to Windows so the default browser is run
OpenURL(url);
}
 

Convert British English punctuation to American English punctuation   (download BritishPunctuation.bm)
// Convert British English punctuation to American English punctuation
// (in Britain, periods and commas are placed outside double quotes)

macro BritishPunctuation()
{
// notice that the double quote character must be escaped with a
// backslash when it appears within a string

// change ".  to  ."
ReplaceAll("\".",  ".\"");

// change ",  to  ,"
ReplaceAll("\"\,", ",\"");
}
 

   Convert small GIFs to BASE64 for use in Mozilla URLs (download base64.bm)

/*********************************************
* This  macro  will  convert  small  gifs to *
* BASE64 so that they might be used in  data *
* urls as implemented in Mozilla.            *
*                                            *
* Instructions:                              *
*                                            *
* 1.  Find  a tiny gif image and open in Hex *
* Mode in Boxer. Save  the resulting file as *
* a .txt file.                               *
*                                            *
* 2. Lose all the stuff that isn't Hex       *
*                                            *
* 3. Run this macro.                         *
*                                            *
* 4. Paste:     "data:image/gif;base64,"     *
* [without  the  quotation  marks]  at   the *
* beginning  of  the line of text you should *
* receive.                                   *
*                                            *
* 5. Copy all and paste into the address bar *
* of Mozilla.                                *
*                                            *
* 6. If the Image  doesn't  work it might be *
* that the image was too  large;  tiny  gifs *
* remember!                                  *
*                                            *
*********************************************/

macro base64()
{
int a, b, len;

b = LineCount;

// Move to the start of the document
StartOfFile;

// Lose all the white space
ReplaceAll(" ", "");

// Move to the start of the document
StartOfFile;


// Make one long line of text
for (a = 1; a < b; a++)
    {
    EndOfLine;
    Delete;
    }

// Replace all the Hex with Binary
ReplaceAll("0", "0000");
ReplaceAll("1", "0001");
ReplaceAll("2", "0010");
ReplaceAll("3", "0011");
ReplaceAll("4", "0100");
ReplaceAll("5", "0101");
ReplaceAll("6", "0110");
ReplaceAll("7", "0111");
ReplaceAll("8", "1000");
ReplaceAll("9", "1001");
ReplaceAll("A", "1010");
ReplaceAll("B", "1011");
ReplaceAll("C", "1100");
ReplaceAll("D", "1101");
ReplaceAll("E", "1110");
ReplaceAll("F", "1111");

// Move to the start of the document
StartOfFile;

// Split the Binary into 6 byte chunks
for (a = 1; a <= LineCount; a++)
    {
    len = (LineLength(a) / 6);
    for (b = 1; b <= len; b++)
        {
        Right;
        Right;
        Right;
        Right;
        Right;
        Right;
        Space;
        }

    }

// Convert the chunks into BASE64
ReplaceAll("000000 ", "A");
ReplaceAll("000001 ", "B");
ReplaceAll("000010 ", "C");
ReplaceAll("000011 ", "D");
ReplaceAll("000100 ", "E");
ReplaceAll("000101 ", "F");
ReplaceAll("000110 ", "G");
ReplaceAll("000111 ", "H");
ReplaceAll("001000 ", "I");
ReplaceAll("001001 ", "J");
ReplaceAll("001010 ", "K");
ReplaceAll("001011 ", "L");
ReplaceAll("001100 ", "M");
ReplaceAll("001101 ", "N");
ReplaceAll("001110 ", "O");
ReplaceAll("001111 ", "P");
ReplaceAll("010000 ", "Q");
ReplaceAll("010001 ", "R");
ReplaceAll("010010 ", "S");
ReplaceAll("010011 ", "T");
ReplaceAll("010100 ", "U");
ReplaceAll("010101 ", "V");
ReplaceAll("010110 ", "W");
ReplaceAll("010111 ", "X");
ReplaceAll("011000 ", "Y");
ReplaceAll("011001 ", "Z");
ReplaceAll("011010 ", "a");
ReplaceAll("011011 ", "b");
ReplaceAll("011100 ", "c");
ReplaceAll("011101 ", "d");
ReplaceAll("011110 ", "e");
ReplaceAll("011111 ", "f");
ReplaceAll("100000 ", "g");
ReplaceAll("100001 ", "h");
ReplaceAll("100010 ", "i");
ReplaceAll("100011 ", "j");
ReplaceAll("100100 ", "k");
ReplaceAll("100101 ", "l");
ReplaceAll("100110 ", "m");
ReplaceAll("100111 ", "n");
ReplaceAll("101000 ", "o");
ReplaceAll("101001 ", "p");
ReplaceAll("101010 ", "q");
ReplaceAll("101011 ", "r");
ReplaceAll("101100 ", "s");
ReplaceAll("101101 ", "t");
ReplaceAll("101110 ", "u");
ReplaceAll("101111 ", "v");
ReplaceAll("110000 ", "w");
ReplaceAll("110001 ", "x");
ReplaceAll("110010 ", "y");
ReplaceAll("110011 ", "z");
ReplaceAll("110100 ", "0");
ReplaceAll("110101 ", "1");
ReplaceAll("110110 ", "2");
ReplaceAll("110111 ", "3");
ReplaceAll("111000 ", "4");
ReplaceAll("111001 ", "5");
ReplaceAll("111010 ", "6");
ReplaceAll("111011 ", "7");
ReplaceAll("111100 ", "8");
ReplaceAll("111101 ", "9");
ReplaceAll("111110 ", "+");
ReplaceAll("111111 ", "/");
}