Skip to content

Instantly share code, notes, and snippets.

@M-griffin
Last active August 29, 2015 14:10
Show Gist options
  • Save M-griffin/63f711bcffbc344f7eae to your computer and use it in GitHub Desktop.
Save M-griffin/63f711bcffbc344f7eae to your computer and use it in GitHub Desktop.
Pipe Codes to ANSI Color ESC sequences
// Pipe Code to ANSI Color Parser
// Michael Griffin (c) 2011
// Donated to DayDream BBS in C, Rework of Enthral BBS from C++
// Compile using gcc in in linux.
// Free to use and modify
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Ansi Forground Escape Sequences
void ansi_fg(char *data, int fg)
{
switch (fg)
{
case 0:
strcat(data, "x[0;30m");
break;
case 1:
strcat(data, "x[0;34m");
break;
case 2:
strcat(data, "x[0;32m");
break;
case 3:
strcat(data, "x[0;36m");
break;
case 4:
strcat(data, "x[0;31m");
break;
case 5:
strcat(data, "x[0;35m");
break;
case 6:
strcat(data, "x[0;33m");
break;
case 7:
strcat(data, "x[0;37m");
break;
case 8:
strcat(data, "x[1;30m");
break;
case 9:
strcat(data, "x[1;34m");
break;
case 10:
strcat(data, "x[1;32m");
break;
case 11:
strcat(data, "x[1;36m");
break;
case 12:
strcat(data, "x[1;31m");
break;
case 13:
strcat(data, "x[1;35m");
break;
case 14:
strcat(data, "x[1;33m");
break;
case 15:
strcat(data, "x[1;37m");
break;
default :
break;
}
data[0] = '\x1b';
}
// Ansi Background Escape Sequences
void ansi_bg(char *data, int bg)
{
switch (bg)
{
case 16:
strcat(data, "x[40m");
break;
case 17:
strcat(data, "x[44m");
break;
case 18:
strcat(data, "x[42m");
break;
case 19:
strcat(data, "x[46m");
break;
case 20:
strcat(data, "x[41m");
break;
case 21:
strcat(data, "x[45m");
break;
case 22:
strcat(data, "x[43m");
break;
case 23:
strcat(data, "x[47m");
break;
// Default to none.
case 24:
strcat(data, "x[0m");
break;
default :
break;
}
data[0] = '\x1b';
}
// Pipe2Ansi, parses all |01 - |23 codes
void pipe2ansi(char* szString)
{
// These should really be dynamic to handle any size.
char szReplace[10] = {0}; // Holds Ansi String Sequence, no longer then 10
// If we parse other data can make this bigger
char *szStrBuilder; // Holds new String being built
// We dynamically allocate this so we never
// Run out of space when building the new string.
int size = strlen(szString); // get size of string we are parsing,
int index = 0; // Index of Pipe Char in String
char* pch; // Pointer to Pipe Char in String if found
// Generic Counters
int i = 0;
int j = 0;
// Search Initial String for Pipe Char, if not found exit, else continue
pch = (char *) memchr (szString, '|', size);
if (pch != NULL)
{
// Calculate Index Position of | char found in string.
index = pch-szString;
//printf("Pipe Code found!: %d, size %d \r\n", index, size);
}
else
{
// No Pipe Code in String
// no need to test further, so return
return;
}
// Setup Loop through String to test and replace pipe codes with
// Ansi ESC Sequences.
for ( ; index < size; index++)
{
// Make sure pipe can't possibly extend past the end of the string.
// End of String reached, no possiable pipe code.
if (index +2 >= size)
return;
// Test if Current Index is a Pipe Code.
if (szString[index] == '|')
{
// Each loop, clear out Char Array to start with fresh ansi string.
memset(&szReplace, 0, sizeof(szReplace));
// Make Sure Both Chars after Pipe Code are Digits or Numbers.
// Else Pass through and Ignore.
if ( isdigit(szString[index+1]) && isdigit(szString[index+2]) )
{
switch (szString[index+1])
{
case '0' : // Parse First Digit 0
switch (szString[index+2])
{
// Parse Second Digit 0 - 9
case '0' :
ansi_fg(szReplace, 0);
break;
case '1' :
ansi_fg(szReplace, 1);
break;
case '2' :
ansi_fg(szReplace, 2);
break;
case '3' :
ansi_fg(szReplace, 3);
break;
case '4' :
ansi_fg(szReplace, 4);
break;
case '5' :
ansi_fg(szReplace, 5);
break;
case '6' :
ansi_fg(szReplace, 6);
break;
case '7' :
ansi_fg(szReplace, 7);
break;
case '8' :
ansi_fg(szReplace, 8);
break;
case '9' :
ansi_fg(szReplace, 9);
break;
default :
break;
}
break;
case '1' : // Parse First Digit 1
switch (szString[index+1])
{
// Parse Second Digit 10 - 19
case '0' :
ansi_fg(szReplace, 10);
break;
case '1' :
ansi_fg(szReplace, 11);
break;
case '2' :
ansi_fg(szReplace, 12);
break;
case '3' :
ansi_fg(szReplace, 13);
break;
case '4' :
ansi_fg(szReplace, 14);
break;
case '5' :
ansi_fg(szReplace, 15);
break;
case '6' :
ansi_bg(szReplace, 16);
break;
case '7' :
ansi_bg(szReplace, 17);
break;
case '8' :
ansi_bg(szReplace, 18);
break;
case '9' :
ansi_bg(szReplace, 19);
break;
default :
break;
}
break;
case '2' : // Parse First Digit 2
switch (szString[index+2])
{
// Parse Second Digit 20 - 23
case '0' :
ansi_bg(szReplace, 20);
break;
case '1' :
ansi_bg(szReplace, 21);
break;
case '2' :
ansi_bg(szReplace, 22);
break;
case '3' :
ansi_bg(szReplace, 23);
break;
default :
break;
}
break;
} // End Switch
// Check if we matched an Ansi Sequence
// If we did, Copy string up to, not including pipe,
// Then con cat new ansi sequence to replace pipe in
// our new string And copy remainder of string back
// to run through Search for next pipe sequence.
if (strcmp(szReplace,"") != 0)
{
//printf("szReplace found! \r\n");
/* Allocate space szStrBuilder to hold new string */
// String Len of Both Origianl string, And Replacement, plus two
// Extra for each '\0' Ending Char in each String.
szStrBuilder = (char *) calloc ((size + ( strlen(szReplace) + 2 )), sizeof(char) );
if (szStrBuilder == NULL)
{
/* Memory could not be allocated, the program should
handle the error here as appropriate. */
return;
}
// Sequence found.
// 1. Copy String up to pipe into new string.
for (i = 0; i < index; i++)
szStrBuilder[i] = szString[i];
// ConCat New Ansi Sequence into String
strcat(szStrBuilder,szReplace);
// Skip Past 2 Digits after pipe, and copy over remainder of
// String into new string so we have a complete string again.
for (i = strlen(szStrBuilder)-1, j = index+3; j < size; i++, j++)
szStrBuilder[i] = szString[j];
// Now reaassign new string back to Original String.
// Make sure we only copy back the same size of the origianl string
// If the string isn't big enough to hold new data, then we will
// overwrite memory.. bad!
// printf ("%d",sizeof(szString));
// snprintf(szString,sizeof(szString),"%s",szStrBuilder);
sprintf(szString,"%s",szStrBuilder);
// Now Free szStrBuilder for next Run
/* Allocation succeeded. Do something. */
free(szStrBuilder); /* We are done with the String objects, and
free the associated memory. */
szStrBuilder = NULL; /* The pointed-to-data must not be used again,
unless re-assigned by using calloc
again. */
// Reset new size of string since ansi sequence is longer
// Then a pipe code.
size = strlen(szString);
// then test again
// if anymore pipe codes exists, if they do repeat process.
pch = (char *) memchr (szString, '|', size);
if (pch != NULL)
{
// Calculate Index Position of | char found in string.
index = pch-szString;
--index; // Loop will incriment this so we need to set it down 1.
//printf("Found second sequence ! index %d, size %d\r\n",index, size);
}
else
{
//printf("Not Found second sequence ! \r\n");
// No Pipe Code in String
// no need to test further, so return
return;
}
}
}
}
} // End of For Loop, Finished.
}
int main(int argc, char *argv[])
{
// Always init Arrays to 0
char tempmem[100] = { 0 };
// Setup String, add 1 bad pipe a| to verify it wil pass through
sprintf(tempmem,"Testing a| string |01 woo |04 woo |03 .. |12 .. .");
// Call Function
pipe2ansi(tempmem);
// Print updated string.
printf("\r\n String: %s \r\n", tempmem);
system("PAUSE");
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment