mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2024-11-08 08:47:17 +01:00
389 lines
8.4 KiB
C
389 lines
8.4 KiB
C
|
/*
|
||
|
* Copyright (C) 2004-2012 George Yunaev gyunaev@ulduzsoft.com
|
||
|
*
|
||
|
* This library is free software; you can redistribute it and/or modify it
|
||
|
* under the terms of the GNU Lesser General Public License as published by
|
||
|
* the Free Software Foundation; either version 3 of the License, or (at your
|
||
|
* option) any later version.
|
||
|
*
|
||
|
* This library is distributed in the hope that it will be useful, but WITHOUT
|
||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||
|
* License for more details.
|
||
|
*/
|
||
|
|
||
|
#include <ctype.h>
|
||
|
|
||
|
#define LIBIRC_COLORPARSER_BOLD (1<<1)
|
||
|
#define LIBIRC_COLORPARSER_UNDERLINE (1<<2)
|
||
|
#define LIBIRC_COLORPARSER_REVERSE (1<<3)
|
||
|
#define LIBIRC_COLORPARSER_COLOR (1<<4)
|
||
|
|
||
|
#define LIBIRC_COLORPARSER_MAXCOLORS 15
|
||
|
|
||
|
|
||
|
static const char * color_replacement_table[] =
|
||
|
{
|
||
|
"WHITE",
|
||
|
"BLACK",
|
||
|
"DARKBLUE",
|
||
|
"DARKGREEN",
|
||
|
"RED",
|
||
|
"BROWN",
|
||
|
"PURPLE",
|
||
|
"OLIVE",
|
||
|
"YELLOW",
|
||
|
"GREEN",
|
||
|
"TEAL",
|
||
|
"CYAN",
|
||
|
"BLUE",
|
||
|
"MAGENTA",
|
||
|
"DARKGRAY",
|
||
|
"LIGHTGRAY",
|
||
|
0
|
||
|
};
|
||
|
|
||
|
|
||
|
static inline void libirc_colorparser_addorcat (char ** destline, unsigned int * destlen, const char * str)
|
||
|
{
|
||
|
unsigned int len = strlen(str);
|
||
|
|
||
|
if ( *destline )
|
||
|
{
|
||
|
strcpy (*destline, str);
|
||
|
*destline += len;
|
||
|
}
|
||
|
else
|
||
|
*destlen += len;
|
||
|
}
|
||
|
|
||
|
|
||
|
static void libirc_colorparser_applymask (unsigned int * mask,
|
||
|
char ** destline, unsigned int * destlen,
|
||
|
unsigned int bitmask, const char * start, const char * end)
|
||
|
{
|
||
|
if ( (*mask & bitmask) != 0 )
|
||
|
{
|
||
|
*mask &= ~bitmask;
|
||
|
libirc_colorparser_addorcat (destline, destlen, end);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*mask |= bitmask;
|
||
|
libirc_colorparser_addorcat (destline, destlen, start);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
static void libirc_colorparser_applycolor (unsigned int * mask,
|
||
|
char ** destline, unsigned int * destlen,
|
||
|
unsigned int colorid, unsigned int bgcolorid)
|
||
|
{
|
||
|
const char * end = "[/COLOR]";
|
||
|
char startbuf[64];
|
||
|
|
||
|
if ( bgcolorid != 0 )
|
||
|
sprintf (startbuf, "[COLOR=%s/%s]", color_replacement_table[colorid], color_replacement_table[bgcolorid]);
|
||
|
else
|
||
|
sprintf (startbuf, "[COLOR=%s]", color_replacement_table[colorid]);
|
||
|
|
||
|
if ( (*mask & LIBIRC_COLORPARSER_COLOR) != 0 )
|
||
|
libirc_colorparser_addorcat (destline, destlen, end);
|
||
|
|
||
|
*mask |= LIBIRC_COLORPARSER_COLOR;
|
||
|
libirc_colorparser_addorcat (destline, destlen, startbuf);
|
||
|
}
|
||
|
|
||
|
|
||
|
static void libirc_colorparser_closetags (unsigned int * mask,
|
||
|
char ** destline, unsigned int * destlen)
|
||
|
{
|
||
|
if ( *mask & LIBIRC_COLORPARSER_BOLD )
|
||
|
libirc_colorparser_applymask (mask, destline, destlen, LIBIRC_COLORPARSER_BOLD, 0, "[/B]");
|
||
|
|
||
|
if ( *mask & LIBIRC_COLORPARSER_UNDERLINE )
|
||
|
libirc_colorparser_applymask (mask, destline, destlen, LIBIRC_COLORPARSER_UNDERLINE, 0, "[/U]");
|
||
|
|
||
|
if ( *mask & LIBIRC_COLORPARSER_REVERSE )
|
||
|
libirc_colorparser_applymask (mask, destline, destlen, LIBIRC_COLORPARSER_REVERSE, 0, "[/I]");
|
||
|
|
||
|
if ( *mask & LIBIRC_COLORPARSER_COLOR )
|
||
|
libirc_colorparser_applymask (mask, destline, destlen, LIBIRC_COLORPARSER_COLOR, 0, "[/COLOR]");
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* IRC to [code] color conversion. Or strip.
|
||
|
*/
|
||
|
static char * libirc_colorparser_irc2code (const char * source, int strip)
|
||
|
{
|
||
|
unsigned int mask = 0, destlen = 0;
|
||
|
char * destline = 0, *d = 0;
|
||
|
const char *p;
|
||
|
int current_bg = 0;
|
||
|
|
||
|
/*
|
||
|
* There will be two passes. First pass calculates the total length of
|
||
|
* the destination string. The second pass allocates memory for the string,
|
||
|
* and fills it.
|
||
|
*/
|
||
|
while ( destline == 0 ) // destline will be set after the 2nd pass
|
||
|
{
|
||
|
if ( destlen > 0 )
|
||
|
{
|
||
|
// This is the 2nd pass; allocate memory.
|
||
|
if ( (destline = malloc (destlen)) == 0 )
|
||
|
return 0;
|
||
|
|
||
|
d = destline;
|
||
|
}
|
||
|
|
||
|
for ( p = source; *p; p++ )
|
||
|
{
|
||
|
switch (*p)
|
||
|
{
|
||
|
case 0x02: // bold
|
||
|
if ( strip )
|
||
|
continue;
|
||
|
|
||
|
libirc_colorparser_applymask (&mask, &d, &destlen, LIBIRC_COLORPARSER_BOLD, "[B]", "[/B]");
|
||
|
break;
|
||
|
|
||
|
case 0x1F: // underline
|
||
|
if ( strip )
|
||
|
continue;
|
||
|
|
||
|
libirc_colorparser_applymask (&mask, &d, &destlen, LIBIRC_COLORPARSER_UNDERLINE, "[U]", "[/U]");
|
||
|
break;
|
||
|
|
||
|
case 0x16: // reverse
|
||
|
if ( strip )
|
||
|
continue;
|
||
|
|
||
|
libirc_colorparser_applymask (&mask, &d, &destlen, LIBIRC_COLORPARSER_REVERSE, "[I]", "[/I]");
|
||
|
break;
|
||
|
|
||
|
case 0x0F: // reset colors
|
||
|
if ( strip )
|
||
|
continue;
|
||
|
|
||
|
libirc_colorparser_closetags (&mask, &d, &destlen);
|
||
|
break;
|
||
|
|
||
|
case 0x03: // set color
|
||
|
if ( isdigit (p[1]) )
|
||
|
{
|
||
|
// Parse
|
||
|
int bgcolor = -1, color = p[1] - 0x30;
|
||
|
p++;
|
||
|
|
||
|
if ( isdigit (p[1]) )
|
||
|
{
|
||
|
color = color * 10 + (p[1] - 0x30);
|
||
|
p++;
|
||
|
}
|
||
|
|
||
|
// If there is a comma, search for the following
|
||
|
// background color
|
||
|
if ( p[1] == ',' && isdigit (p[2]) )
|
||
|
{
|
||
|
bgcolor = p[2] - 0x30;
|
||
|
p += 2;
|
||
|
|
||
|
if ( isdigit (p[1]) )
|
||
|
{
|
||
|
bgcolor = bgcolor * 10 + (p[1] - 0x30);
|
||
|
p++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Check for range
|
||
|
if ( color <= LIBIRC_COLORPARSER_MAXCOLORS
|
||
|
&& bgcolor <= LIBIRC_COLORPARSER_MAXCOLORS )
|
||
|
{
|
||
|
if ( strip )
|
||
|
continue;
|
||
|
|
||
|
if ( bgcolor != -1 )
|
||
|
current_bg = bgcolor;
|
||
|
|
||
|
libirc_colorparser_applycolor (&mask, &d, &destlen, color, current_bg);
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
if ( destline )
|
||
|
*d++ = *p;
|
||
|
else
|
||
|
destlen++;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Close all the opened tags
|
||
|
libirc_colorparser_closetags (&mask, &d, &destlen);
|
||
|
destlen++; // for 0-terminator
|
||
|
}
|
||
|
|
||
|
*d = '\0';
|
||
|
return destline;
|
||
|
}
|
||
|
|
||
|
|
||
|
static int libirc_colorparser_colorlookup (const char * color)
|
||
|
{
|
||
|
int i;
|
||
|
for ( i = 0; color_replacement_table[i]; i++ )
|
||
|
if ( !strcmp (color, color_replacement_table[i]) )
|
||
|
return i;
|
||
|
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* [code] to IRC color conversion.
|
||
|
*/
|
||
|
char * irc_color_convert_to_mirc (const char * source)
|
||
|
{
|
||
|
unsigned int destlen = 0;
|
||
|
char * destline = 0, *d = 0;
|
||
|
const char *p1, *p2, *cur;
|
||
|
|
||
|
/*
|
||
|
* There will be two passes. First pass calculates the total length of
|
||
|
* the destination string. The second pass allocates memory for the string,
|
||
|
* and fills it.
|
||
|
*/
|
||
|
while ( destline == 0 ) // destline will be set after the 2nd pass
|
||
|
{
|
||
|
if ( destlen > 0 )
|
||
|
{
|
||
|
// This is the 2nd pass; allocate memory.
|
||
|
if ( (destline = malloc (destlen)) == 0 )
|
||
|
return 0;
|
||
|
|
||
|
d = destline;
|
||
|
}
|
||
|
|
||
|
cur = source;
|
||
|
while ( (p1 = strchr (cur, '[')) != 0 )
|
||
|
{
|
||
|
const char * replacedval = 0;
|
||
|
p2 = 0;
|
||
|
|
||
|
// Check if the closing bracket is available after p1
|
||
|
// and the tag length is suitable
|
||
|
if ( p1[1] != '\0'
|
||
|
&& (p2 = strchr (p1, ']')) != 0
|
||
|
&& (p2 - p1) > 1
|
||
|
&& (p2 - p1) < 31 )
|
||
|
{
|
||
|
// Get the tag
|
||
|
char tagbuf[32];
|
||
|
int taglen = p2 - p1 - 1;
|
||
|
|
||
|
memcpy (tagbuf, p1 + 1, taglen);
|
||
|
tagbuf[taglen] = '\0';
|
||
|
|
||
|
if ( !strcmp (tagbuf, "/COLOR") )
|
||
|
replacedval = "\x0F";
|
||
|
else if ( strstr (tagbuf, "COLOR=") == tagbuf )
|
||
|
{
|
||
|
int color, bgcolor = -2;
|
||
|
char * bcol;
|
||
|
|
||
|
bcol = strchr (tagbuf + 6, '/');
|
||
|
|
||
|
if ( bcol )
|
||
|
{
|
||
|
*bcol++ = '\0';
|
||
|
bgcolor = libirc_colorparser_colorlookup (bcol);
|
||
|
}
|
||
|
|
||
|
color = libirc_colorparser_colorlookup (tagbuf + 6);
|
||
|
|
||
|
if ( color != -1 && bgcolor == -2 )
|
||
|
{
|
||
|
sprintf (tagbuf, "\x03%02d", color);
|
||
|
replacedval = tagbuf;
|
||
|
}
|
||
|
else if ( color != -1 && bgcolor >= 0 )
|
||
|
{
|
||
|
sprintf (tagbuf, "\x03%02d,%02d", color, bgcolor);
|
||
|
replacedval = tagbuf;
|
||
|
}
|
||
|
}
|
||
|
else if ( !strcmp (tagbuf, "B") || !strcmp (tagbuf, "/B") )
|
||
|
replacedval = "\x02";
|
||
|
else if ( !strcmp (tagbuf, "U") || !strcmp (tagbuf, "/U") )
|
||
|
replacedval = "\x1F";
|
||
|
else if ( !strcmp (tagbuf, "I") || !strcmp (tagbuf, "/I") )
|
||
|
replacedval = "\x16";
|
||
|
}
|
||
|
|
||
|
if ( replacedval )
|
||
|
{
|
||
|
// add a part before the tag
|
||
|
int partlen = p1 - cur;
|
||
|
|
||
|
if ( destline )
|
||
|
{
|
||
|
memcpy (d, cur, partlen);
|
||
|
d += partlen;
|
||
|
}
|
||
|
else
|
||
|
destlen += partlen;
|
||
|
|
||
|
// Add the replacement
|
||
|
libirc_colorparser_addorcat (&d, &destlen, replacedval);
|
||
|
|
||
|
// And move the pointer
|
||
|
cur = p2 + 1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// add a whole part before the end tag
|
||
|
int partlen;
|
||
|
|
||
|
if ( !p2 )
|
||
|
p2 = cur + strlen(cur);
|
||
|
|
||
|
partlen = p2 - cur + 1;
|
||
|
|
||
|
if ( destline )
|
||
|
{
|
||
|
memcpy (d, cur, partlen);
|
||
|
d += partlen;
|
||
|
}
|
||
|
else
|
||
|
destlen += partlen;
|
||
|
|
||
|
// And move the pointer
|
||
|
cur = p2 + 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Add the rest of string
|
||
|
libirc_colorparser_addorcat (&d, &destlen, cur);
|
||
|
destlen++; // for 0-terminator
|
||
|
}
|
||
|
|
||
|
*d = '\0';
|
||
|
return destline;
|
||
|
}
|
||
|
|
||
|
|
||
|
char * irc_color_strip_from_mirc (const char * message)
|
||
|
{
|
||
|
return libirc_colorparser_irc2code (message, 1);
|
||
|
}
|
||
|
|
||
|
|
||
|
char * irc_color_convert_from_mirc (const char * message)
|
||
|
{
|
||
|
return libirc_colorparser_irc2code (message, 0);
|
||
|
}
|