30 Jun, 2011, Rarva.Riendf wrote in the 41st comment:
Votes: 0
Let it go, I will code something that I can understand myself ;p
Should be easy to go from the end of the string to the start and remove duplicated colors

something like that:
previouscolor = none
from end of string to beginning {
color = detect(color)
if (previsouscolor == color)
remove(previsoucolor)
if (isAdjacentColor) //cause having two colors in a rowmeans only the last one will be used
remove(color)
else
previouscolor = color
}
and thats it, algorthm should work fine, not easy to code as it imply to go back and forth in the string, but the logic of it is easier to read this way.

I could not make scandum snippet works and Tyche seems have problem as well.
I am not a fan of coding myself those things as I usually fuck up something (string replacement that can still be freed once done is nightmarish)
But at least I will be able to understand the code I did ;p
30 Jun, 2011, David Haley wrote in the 42nd comment:
Votes: 0
Scandum said:
Haley's having a classic case of tunnel vision and fails to grasp that if the maximum possible input increase is less than the output buffer size there's no need for buffer checks.

I'm not sure you've been paying any attention whatsoever – this isn't even what we were talking about…
Although, of course, it is an issue as well…!

God knows that when Tyche and I agree, the world is about to end, and even he says: "This look ahead crap will ALWAYS bite you in the ass. "

Rarva said:
I could not make scandum snippet works and Tyche seems have problem as well.
I am not a fan of coding myself those things as I usually fuck up something (string replacement that can still be freed once done is nightmarish)
But at least I will be able to understand the code I did ;p

Send me test cases, like a few cases of sample input and corresponding desired output, and I will write the code myself. I'll put my money where my mouth is, if you give me the test scaffolding around it. :smile:
30 Jun, 2011, Rarva.Riendf wrote in the 43rd comment:
Votes: 0
Quote
Send me test cases, like a few cases of sample input and corresponding desired output, and I will write the code myself. I'll put my money where my mouth is, if you give me the test scaffolding around it. :smile:


Well as a matter of fact, considering how fucked up the code would be to remove color in my case I gave up and instead made so I do not duplicate colors in the first place as much as I can. (and learned in the process than sprintf(buf, "%s%s", buf, color) works but not sprintf(buf, "%s%s", color, buf) , guess it does not make an internal copy first…nothing in the help I found about sprintf tells about it…I LOVE C…..

test cases would give that otherwise (&0 being my null color, that is why when I dynamically build a buffer I sometimes end up with cases like these)

so as an example &23c&0&12o&0&3l&3&3o&5r should be compressed in &23c&12o&3lo&5r

Tyche snippet works flawlessly but unfortunately I am stucked with a stupid system that use either 1 or 2 number values for colors….
I think I will eventually totally swap to a simpler system using either scandum or kavir color system but it would need a parsing of all the areas to modify the color used.
So dont lose your time, not worth it, unless someone else need it. Was worth asking if anyboy already made it though.
30 Jun, 2011, David Haley wrote in the 44th comment:
Votes: 0
Well, it also doesn't say that it does make an internal copy. Why would it? In very many cases, you don't have overlapping buffers. So it would be wasteful to make a copy in the average case.

FWIW my copy of man printf does warn about the argument strings not overlapping.
30 Jun, 2011, Rarva.Riendf wrote in the 45th comment:
Votes: 0
David Haley said:
FWIW my copy of man printf does warn about the argument strings not overlapping.

Would you have a good link for C documentation on internet ? Most are incomplete especially on those warning (The one I have do warn for some commands, like strcat but not for this one)
It is very annoying to discover those thing afterwards.

abot color I jsut found something funny on my mud …if you put a bacground color code followed by a bold color code, you have the boldcolor on the backgrond, but that does not work with a light color..

ie:\e
Would you have a good link for C documentation on internet ? Most are incomplete especially on those warning (The one I have do warn for some commands, like strcat but not for this one)
It is very annoying to discover those thing afterwards.

abot color I jsut found something funny on my mud …if you put a bacground color code followed by a bold color code, you have the boldcolor on the backgrond, but that does not work with a light color..

ie:\e[0;43m\x1B[1;31m give me a bold red with a yellow background
but \e[0;43m\x1B[31m will just give me red…strange world of telnet..
01 Jul, 2011, Scandum wrote in the 46th comment:
Votes: 0
Tyche said:
It doesn't really remove unneeded color codes.

Hrm, I should have properly tested that addition.

Tyche said:
It doesn't handle the 'today^^s' above correctly. I was expecting ^^ to be an escape for ^ and generate no color code.
Also it keeps the invalid color code ^D in the string, but not the invalid color code ^Z.

Guess I can check for ^^ and I've switched to using a lookup table, so whatever caused the ^D ^Z issue should be resolved.
01 Jul, 2011, Scandum wrote in the 47th comment:
Votes: 0
Alright, I've tested this code and as far as I can tell everything works with no obvious kinks. The ANSI codes are no longer supported, and background color support has been commented out. The function call is slightly different, and support for a no color mode has been added.

As has been previously discussed, the code still operates in the same manner most people prefer their sexual intercourse, wild and without protection.

/*
xterm 256 color code parser by Igor van den Hoven

v1.0 02/11/2009
v1.4 06/24/2011 v1.4.2 06/30/2011

This code is placed in the public domain.
*/

/*
For xterm 256 color foreground colors use:

<aaa> to <fff> for RGB foreground colors

<g00> to <g23> for grayscale foreground colors


For xterm 256 color background colors use:

<AAA> to <FFF> for RGB background colors

<G00> to <G23> for grayscale background colors

Background color support is commented out by default


With 256 colors disabled colors are converted to 16 color ANSI.
*/

/*
For 32 color codes use:

^a - dark azure ^A - azure
^b - dark blue ^B - blue
^c - dark cyan ^C - cyan
^e - dark ebony ^E - ebony
^g - dark green ^G - green
^j - dark jade ^J - jade
^l - dark lime ^L - lime
^m - dark magenta ^M - magenta
^o - dark orange ^O - orange
^p - dark pink ^P - pink
^r - dark red ^R - red
^s - dark silver ^S - silver
^t - dark tan ^T - tan
^v - dark violet ^V - violet
^w - dark white ^W - white
^y - dark yellow ^Y - yellow


With 256 colors disabled colors are converted to 16 color ANSI.
*/

#include <stdio.h>
#include <string.h>

/*
256 to 16 color conversion table
*/

char *ansi_colors[256] =
{
"\e =
{
"\e[22;30m", "\e[22;31m", "\e[22;32m", "\e[22;33m", "\e[22;34m", "\e[22;35m", "\e[22;36m", "\e[22;37m",
"\e[1;30m", "\e[1;31m", "\e[1;32m", "\e[1;33m", "\e[1;34m", "\e[1;35m", "\e[1;36m", "\e[1;37m",

"\e[22;30m", "\e[22;34m", "\e[22;34m", "\e[22;34m", "\e[1;34m", "\e[1;34m",
"\e[22;32m", "\e[22;36m", "\e[22;36m", "\e[22;34m", "\e[1;34m", "\e[1;34m",
"\e[22;32m", "\e[22;36m", "\e[22;36m", "\e[22;36m", "\e[1;34m", "\e[1;34m",
"\e[22;32m", "\e[22;32m", "\e[22;36m", "\e[22;36m", "\e[22;36m", "\e[1;36m",
"\e[1;32m", "\e[1;32m", "\e[1;32m", "\e[22;36m", "\e[1;36m", "\e[1;36m",
"\e[1;32m", "\e[1;32m", "\e[1;32m", "\e[1;36m", "\e[1;36m", "\e[1;36m",

"\e[22;31m", "\e[22;35m", "\e[22;35m", "\e[22;34m", "\e[1;34m", "\e[1;34m",
"\e[22;33m", "\e[1;30m", "\e[22;34m", "\e[22;34m", "\e[1;34m", "\e[1;34m",
"\e[22;33m", "\e[22;32m", "\e[22;36m", "\e[22;36m", "\e[1;34m", "\e[1;34m",
"\e[22;32m", "\e[22;32m", "\e[22;36m", "\e[22;36m", "\e[22;36m", "\e[1;36m",
"\e[1;32m", "\e[1;32m", "\e[1;32m", "\e[22;36m", "\e[1;36m", "\e[1;36m",
"\e[1;32m", "\e[1;32m", "\e[1;32m", "\e[1;36m", "\e[1;36m", "\e[1;36m",

"\e[22;31m", "\e[22;35m", "\e[22;35m", "\e[22;35m", "\e[1;34m", "\e[1;34m",
"\e[22;33m", "\e[22;31m", "\e[22;35m", "\e[22;35m", "\e[1;34m", "\e[1;34m",
"\e[22;33m", "\e[22;33m", "\e[22;37m", "\e[22;34m", "\e[1;34m", "\e[1;34m",
"\e[22;33m", "\e[22;33m", "\e[22;32m", "\e[22;36m", "\e[22;36m", "\e[1;34m",
"\e[1;32m", "\e[1;32m", "\e[1;32m", "\e[22;36m", "\e[1;36m", "\e[1;36m",
"\e[1;32m", "\e[1;32m", "\e[1;32m", "\e[1;32m", "\e[1;36m", "\e[1;36m",

"\e[22;31m", "\e[22;31m", "\e[22;35m", "\e[22;35m", "\e[22;35m", "\e[1;35m",
"\e[22;31m", "\e[22;31m", "\e[22;35m", "\e[22;35m", "\e[22;35m", "\e[1;35m",
"\e[22;33m", "\e[22;33m", "\e[22;31m", "\e[22;35m", "\e[22;35m", "\e[1;34m",
"\e[22;33m", "\e[22;33m", "\e[22;33m", "\e[22;37m", "\e[1;34m", "\e[1;34m",
"\e[22;33m", "\e[22;33m", "\e[22;33m", "\e[1;32m", "\e[1;36m", "\e[1;36m",
"\e[1;33m", "\e[1;33m", "\e[1;32m", "\e[1;32m", "\e[1;36m", "\e[1;36m",

"\e[1;31m", "\e[1;31m", "\e[1;31m", "\e[22;35m", "\e[1;35m", "\e[1;35m",
"\e[1;31m", "\e[1;31m", "\e[1;31m", "\e[22;35m", "\e[1;35m", "\e[1;35m",
"\e[1;31m", "\e[1;31m", "\e[1;31m", "\e[22;35m", "\e[1;35m", "\e[1;35m",
"\e[22;33m", "\e[22;33m", "\e[22;33m", "\e[1;31m", "\e[1;35m", "\e[1;35m",
"\e[1;33m", "\e[1;33m", "\e[1;33m", "\e[1;33m", "\e[1;37m", "\e[1;37m",
"\e[1;33m", "\e[1;33m", "\e[1;33m", "\e[1;33m", "\e[1;37m", "\e[1;37m",

"\e[1;31m", "\e[1;31m", "\e[1;31m", "\e[1;35m", "\e[1;35m", "\e[1;35m",
"\e[1;31m", "\e[1;31m", "\e[1;31m", "\e[1;35m", "\e[1;35m", "\e[1;35m",
"\e[1;31m", "\e[1;31m", "\e[1;31m", "\e[1;31m", "\e[1;35m", "\e[1;35m",
"\e[1;33m", "\e[1;33m", "\e[1;31m", "\e[1;31m", "\e[1;35m", "\e[1;35m",
"\e[1;33m", "\e[1;33m", "\e[1;33m", "\e[1;33m", "\e[1;37m", "\e[1;37m",
"\e[1;33m", "\e[1;33m", "\e[1;33m", "\e[1;33m", "\e[1;37m", "\e[1;37m",

"\e[1;30m", "\e[1;30m", "\e[1;30m", "\e[1;30m", "\e[1;30m", "\e[1;30m",
"\e[1;30m", "\e[1;30m", "\e[1;30m", "\e[1;30m", "\e[1;30m", "\e[1;30m",
"\e[22;37m", "\e[22;37m", "\e[22;37m", "\e[22;37m", "\e[22;37m", "\e[22;37m",
"\e[1;37m", "\e[1;37m", "\e[1;37m", "\e[1;37m", "\e[1;37m", "\e[1;37m"
};

/*
32 to 256 color conversion table
*/

char *alphabet_colors_dark[26] =
{
"<abd>", "<aad>", "<add>", "", "<g04>", "", "<ada>", "", "", "<adb>", "", "<bda>", "<dad>",
"", "<dba>", "<dab>", "", "<daa>", "<ccc>", "<cba>", "", "<bad>", "<ddd>", "", "<dda>", ""
};

char *alphabet_colors_bold[26] =
{
"<acf>", "<aaf>", "<aff>", "", "<bbb>", "", "<afa>", "", "", "<afc>", "", "<cfa>", "<faf>",
"", "<fca>", "<fac>", "", "<faa>", "<eee>", "<eda>", "", "<caf>", "<fff>", "", "<ffa>", ""
};


// Make sure that the output buffer remains at least 4 times larger than the user input buffer.

// colors should either be 0 for no colors, 16 for ansi colors, or 256 for xterm 256 colors.

int substitute_color(char *input, char *output, int colors)
{
char *pti, *pto, old[6] = { 0 };

pti = input;
pto = output;

while (*pti)
{
switch (*pti)
{
case '^':
if (isalpha(pti[1]))
{
if (pti[2] == '^' && isalpha(pti[3]))
{
pti += 2;
continue;
}

if (strncmp(old, pti, 2) && colors)
{
if (pti[1] >= 'a' && pti[1] <= 'z')
{
pto += substitute_color(alphabet_colors_dark[pti[1] - 'a'], pto, colors);
}
else
{
pto += substitute_color(alphabet_colors_bold[pti[1] - 'A'], pto, colors);
}
}
pti += sprintf(old, "%c%c", pti[0], pti[1]);
}
else
{
if (pti[1] == '^')
{
pti++;
}
*pto++ = *pti++;
}
break;

case '<':
if (pti[1] >= 'a' && pti[1] <= 'f' && pti[2] >= 'a' && pti[2] <= 'f' && pti[3] >= 'a' && pti[3] <= 'f' && pti[4] == '>')
{
if (strncmp(old, pti, 5) && colors)
{
if (colors == 256)
{
pto += sprintf(pto, "\033[38;5;%dm", 16 + (pti[1] - 'a') * 36 + (pti[2] - 'a') * 6 + (pti[3] - 'a'));
}
else
{
pto += substitute_color(ansi_colors[16 + (pti[1] - 'a') * 36 + (pti[2] - 'a') * 6 + (pti[3] - 'a')], pto, colors);
}
}
pti += sprintf(old, "<%c%c%c>", pti[1], pti[2], pti[3]);
}
/*
else if (pti[1] >= 'A' && pti[1] <= 'F' && pti[2] >= 'A' && pti[2] <= 'F' && pti[3] >= 'A' && pti[3] <= 'F' && pti[4] == '>')
{
if (colors == 256)
{
pto += sprintf(pto, "\033[48;5;%dm", 16 + (pti[1] - 'A') * 36 + (pti[2] - 'A') * 6 + (pti[3] - 'A'));
}
else if (colors)
{
pto += sprintf(pto, "\033[4%dm", (pti[1] && pti[1] >= pti[2] ? pti[1] >= pti[3] : 0) + (pti[2] && pti[2] >= pti[1] ? pti[2] >= pti[3] : 0) * 2 + (pti[3] && pti[3] >= pti[2] ? pti[3] >= pti[1] : 0) * 4);
}
pti += 5;
}
*/
else if (pti[1] == 'g' && isdigit((int) pti[2]) && isdigit((int) pti[3]) && (pti[2] - '0') * 10 + (pti[3] - '0') >= 0 && (pti[2] - '0') * 10 + (pti[3] - '0') < 24 && pti[4] == '>')
{
if (strncmp(old, pti, 5) && colors)
{
if (colors == 256)
{
pto += sprintf(pto, "\033[38;5;%dm", 232 + (pti[2] - '0') * 10 + (pti[3] - '0'));
}
else
{
pto += substitute_color(ansi_colors[232 + (pti[2] - '0') * 10 + (pti[3] - '0')], pto, colors);
}
}
pti += sprintf(old, "<%c%c%c>", pti[1], pti[2], pti[3]);
}
/*
else if (pti[1] == 'G' && isdigit((int) pti[2]) && isdigit((int) pti[3]) && (pti[2] - '0') * 10 + (pti[3] - '0') >= 0 && (pti[2] - '0') * 10 + (pti[3] - '0') < 24 && pti[4] == '>')
{
if (colors == 256)
{
pto += sprintf(pto, "\033[48;5;%dm", 232 + (pti[2] - '0') * 10 + (pti[3] - '0'));
}
else if (colors)
{
pto += sprintf(pto, "\033[4%dm", ((pti[2] - '0') * 10 + (pti[3] - '0')) / 12 ? 7 : 0);
}
pti += 5;
}
*/
else
{
*pto++ = *pti++;
}
break;

default:
*pto++ = *pti++;
break;
}
}
*pto = 0;

return pto - output;
}
[/code]
01 Jul, 2011, Tyche wrote in the 48th comment:
Votes: 0
This is pretty much the same code as before, I just added another state.

Using color codes that are one or two digits are inherently ambiguous.
It makes it impossible to color code the digits themselves.
For instance given &1 is RED and &12 is YELLOW, then you can't encode a RED number 2 (at least not without an intervening space).

/*
strip unneccessary color changes from string
string is modified in place

st - state
lc - last color value
cc - current color
d1 - first digit
rp - read pointer
wp - write pointer
esc - escape character
*/
char *strip_colors(char *s,size_t sz) {
enum {normal, escaped, digits} st=normal;
char lc=0,cc,d1,*rp=s,*wp=s,esc=046;
while (*rp && rp != s+sz) {
switch (st) {
case normal:
if (*rp==esc) st=escaped;
else *wp++=*rp;
break;
case escaped:
if (*rp>=0x30 && *rp<=0x39) {d1 = *rp; st=digits;}
else {*wp++=esc;*wp++=*rp;st=normal;}
break;
case digits:
if (*rp>=0x30 && *rp<=0x39) {
cc = ((d1-0x30)*10)+(*rp-0x30);
if (lc != cc) {lc=cc;*wp++=esc;*wp++=d1;*wp++=*rp;}
} else {
cc = (d1-0x30);
if (lc != cc) {lc=cc;*wp++=esc;*wp++=d1;}
*wp++=*rp;
}
st=normal;
}
rp++;
}
*wp=0;
return s;
}
01 Jul, 2011, Rarva.Riendf wrote in the 49th comment:
Votes: 0
Quote
For instance given &1 is RED and &12 is YELLOW, then you can't encode a RED number 2 (at least not without an intervening space).

Yep it is a pain in the ass…but I am not a fan of too colorful mud anyway I think colors should be reserved to very few items/description or you end up with a rainbow in your face unreadable mess. so I deal with it.
And I really like your code Tyche: hard to read/understand what it does at a glance but way more generic and upgradable. You should make it a snippet.
This whole mess came in after I implemented the mapmakerv2, and the pager being overflowed and crashing (because of a 50000 char map), and the need for a color compression.
Since then I fixed the pager so it works, (with a dynamically allowed buffer) and modified mapmakerv2 so the it remembers the last color used before applying the same. (same map came from 50000char to 11000)

So I personally dont really need a compression system as much anymore, I will put it in as it is not very cpu taxing and can still save a little bandwidth here and there.
It will probably has some use for the livemaze I modified as well :)

Will put in both modified snippets soon for the one who cares, once I ran then in Valgrind with limits case to be sure I did not fucked up anything
01 Jul, 2011, Rarva.Riendf wrote in the 50th comment:
Votes: 0
@Tyche yorur code 'seems' to escape a color if it is followed by a blank space, while it should not.
I say seem cause I am totally sure about it, but when I removed the strip color it looked ok..I am looking into it, unless you tell me it is perfectly normal 'as is'

hhm weird
"+&1o&9+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n\r|&1o&9&1o&9&1o&9&1o&9&1o&9 |&1o&9&1o&9&1o&9 |
gives
"+&1o&9+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n\r|&1o&9&1o&1o&1o&1o |&1o&9&1o&1o | |

when wanted result shoudl be
"+&1o&9+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n\r|&1ooooo&9 |&1ooo&9 |
01 Jul, 2011, Tyche wrote in the 51st comment:
Votes: 0
Rarva said:
hhm weird
"+&1o&9+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n\r|&1o&9&1o&9&1o&9&1o&9&1o&9 |&1o&9&1o&9&1o&9 |
gives
"+&1o&9+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n\r|&1o&9&1o&1o&1o&1o |&1o&9&1o&1o | |


Well the bug is that it should have returned the same exact string.
This fixes that.
case digits:
if (*rp>=0x30 && *rp<=0x39) {
cc = ((d1-0x30)*10)+(*rp-0x30);
if (lc != cc) {lc=cc;*wp++=esc;*wp++=d1;*wp++=*rp;}
st=normal;
} else {
cc = (d1-0x30);
if (lc != cc) {lc=cc;*wp++=esc;*wp++=d1;}
if (*rp==esc) st=escaped;
else {*wp++=*rp; st=normal;}
}


It was written to only remove unnecessary colors. (color codes that repeat with no intervening change).
I have no way of knowing what your color scheme is beyond an escape followed by one or two digits.
So I don't assume that in '&9&1' that the '&9' should be removed because it might be a foreground/background
combination. Or one is a reset, blink, reverse, etc.

The only point of posting the code is just to illustrate some of the points I made earlier.
01 Jul, 2011, Rarva.Riendf wrote in the 52nd comment:
Votes: 0
Heh ok.

Quote
I have no way of knowing what your color scheme is beyond an escape followed by one or two digits.
So I don't assume that in '&9&1' that the '&9' should be removed because it might be a foreground/background
combination. Or one is a reset, blink, reverse, etc.

The only point of posting the code is just to illustrate some of the points I made earlier.

Indeed. Case closed for me then as I made so what I wanted is not that needed anymore. ( better fix the source of the problem than afterwards anyway)
40.0/52