mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2024-11-08 08:47:17 +01:00
bedf03c9cd
Fixed a bug in the Routine system that caused crashes when constructed with only the first three arguments because it wasn't attached. Implemented a gentle release of functions to not release them if the reference count is 1. Adjusted the Routine and Command system to not be necessary to include them in the module core. Moved the INI and XML libraries into their own namespace. Various other modifications and fixes.
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);
|
|
}
|