unrealircd

- supernets unrealircd source & configuration
git clone git://git.acid.vegas/unrealircd.git
Log | Files | Refs | Archive | README | LICENSE

rtf.c (18912B)

      1 /************************************************************************
      2  *   IRC - Internet Relay Chat, windows/rtf.c
      3  *   Copyright (C) 2004 Dominick Meglio (codemastr)
      4  *   
      5  *   This program is free software; you can redistribute it and/or modify
      6  *   it under the terms of the GNU General Public License as published by
      7  *   the Free Software Foundation; either version 1, or (at your option)
      8  *   any later version.
      9  *
     10  *   This program is distributed in the hope that it will be useful,
     11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13  *   GNU General Public License for more details.
     14  *
     15  *   You should have received a copy of the GNU General Public License
     16  *   along with this program; if not, write to the Free Software
     17  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
     18  */
     19 
     20 #include "unrealircd.h"
     21 #include "win.h"
     22 
     23 unsigned char *RTFBuf;
     24 
     25 #define MIRC_COLORS "{\\colortbl;\\red255\\green255\\blue255;\\red0\\green0\\blue127;\\red0\\green147\\blue0;\\red255\\green0\\blue0;\\red127\\green0\\blue0;\\red156\\green0\\blue156;\\red252\\green127\\blue0;\\red255\\green255\\blue0;\\red0\\green252\\blue0;\\red0\\green147\\blue147;\\red0\\green255\\blue255;\\red0\\green0\\blue252;\\red255\\green0\\blue255;\\red127\\green127\\blue127;\\red210\\green210\\blue210;\\red0\\green0\\blue0;}"
     26 
     27 /* Splits the file up for the EM_STREAMIN message
     28  * Parameters:
     29  *  dwCookie - The file information to split
     30  *  pbBuff   - The output buffer
     31  *  cb       - The size of pbBuff
     32  *  pcb      - The total bytes written to bpBuff
     33  * Returns:
     34  *  Returns 0 to indicate success
     35  */
     36 DWORD CALLBACK SplitIt(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
     37 {
     38 	StreamIO *stream = (StreamIO*)dwCookie;
     39 	if (*stream->size == 0)
     40 	{
     41 		pcb = 0;
     42 		*stream->buffer = 0;
     43 	}
     44 	else if (cb <= *stream->size) 
     45 	{
     46 		memcpy(pbBuff, *stream->buffer, cb);
     47 		*stream->buffer += cb;
     48 		*stream->size -= cb;
     49 		*pcb = cb;
     50 
     51 	}
     52 	else 
     53 	{
     54 		memcpy(pbBuff, *stream->buffer, *stream->size);
     55 		*pcb = *stream->size;
     56 		*stream->size = 0;
     57 	}
     58 	return 0;
     59 }
     60 
     61 /* Reassembles the RTF buffer from EM_STREAMOUT
     62  * Parameters:
     63  *  dwCookie - Unused
     64  *  pbBuff   - The input buffer
     65  *  cb       - The length of the input buffer
     66  *  pcb      - The total bytes read from pbBuff
     67  * Returns:
     68  *  0 to indicate success
     69  * Side Effects:
     70  *  RTFBuf contains the assembled RTF buffer
     71  */
     72 DWORD CALLBACK BufferIt(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
     73 {
     74 	unsigned char *buf2;
     75 	static long size = 0;
     76 	if (!RTFBuf)
     77 		size = 0;
     78 
     79 	buf2 = safe_alloc(size+cb+1);
     80 
     81 	if (RTFBuf)
     82 		memcpy(buf2,RTFBuf,size);
     83 
     84 	memcpy(buf2+size,pbBuff,cb);
     85 
     86 	size += cb;
     87 	safe_free(RTFBuf);
     88 
     89 	RTFBuf = buf2;
     90 
     91 	pcb = &cb;
     92 	return 0;
     93 }
     94 
     95 /* Pushes a color onto the stack
     96  * Parameters:
     97  *  color - The color to add to the stack
     98  *  stack - The stack to add the color to
     99  */
    100 void ColorPush(unsigned char *color, IRCColor **stack)
    101 {
    102 	IRCColor *t = safe_alloc(sizeof(IRCColor));
    103 	safe_strdup(t->color, color);
    104 	t->next = *stack;
    105 	(*stack) = t;
    106 }
    107 
    108 /* Pops a color off of the stack
    109  * Parameters:
    110  *  stack - The stack to pop from
    111  */
    112 void ColorPop(IRCColor **stack)
    113 {
    114 	IRCColor *p = *stack;
    115 	if (!(*stack))
    116 		return;
    117 	safe_free(p->color);
    118 	
    119 	*stack = p->next;
    120 	safe_free(p);
    121 }
    122 
    123 /* Completely empties the color stack
    124  * Parameters:
    125  *  stack - The stack to empty
    126  */
    127 void ColorEmpty(IRCColor **stack)
    128 {
    129 	IRCColor *t, *next;
    130 	for (t = *stack; t; t = next)
    131 	{
    132 		next = t->next;
    133 		safe_free(t->color);
    134 		safe_free(t);
    135 	}
    136 }
    137 
    138 #define iseol(x) ((x) == '\r' || (x) == '\n')
    139 
    140 /* Converts a string in RTF format to IRC codes
    141  * Parameters:
    142  *  fd     - The file descriptor to write to
    143  *  pbBuff - The buffer containing the RTF text
    144  *  cb     - The length of the RTF text
    145  */
    146 DWORD CALLBACK RTFToIRC(int fd, unsigned char *pbBuff, long cb) 
    147 {
    148 	unsigned char *buffer = safe_alloc(cb*2+2);
    149 	int colors[17], bold = 0, uline = 0, incolor = 0, inbg = 0;
    150 	int lastwascf = 0, lastwascf0 = 0;
    151 	int i = 0;
    152 
    153 	IRCColor *TextColors = NULL;
    154 	IRCColor *BgColors = NULL;
    155 	
    156 	memset(buffer, 0, cb);
    157 
    158 	for (; *pbBuff; pbBuff++)
    159 	{
    160 		if (iseol(*pbBuff) || *pbBuff == '{' || *pbBuff == '}')
    161 			continue;
    162 		else if (*pbBuff == '\\')
    163 		{
    164 			/* RTF control sequence */
    165 			pbBuff++;
    166 			if (*pbBuff == '\\' || *pbBuff == '{' || *pbBuff == '}')
    167 				buffer[i++] = *pbBuff;
    168 			else if (*pbBuff == '\'')
    169 			{
    170 				/* Extended ASCII character */
    171 				unsigned char ltr, ultr[3];
    172 				ultr[0] = *(++pbBuff);
    173 				ultr[1] = *(++pbBuff);
    174 				ultr[2] = 0;
    175 				ltr = strtoul(ultr,NULL,16);
    176 				buffer[i++] = ltr;
    177 			}
    178 			else
    179 			{
    180 				int j;
    181 				char cmd[128];
    182 				/* Capture the control sequence */
    183 				for (j = 0; *pbBuff && *pbBuff != '\\' && !isspace(*pbBuff) &&
    184 					!iseol(*pbBuff); pbBuff++)
    185 				{
    186 					cmd[j++] = *pbBuff;
    187 				}
    188 				if (*pbBuff != ' ')
    189 					pbBuff--;
    190 				cmd[j] = 0;
    191 				if (!strcmp(cmd, "fonttbl{"))
    192 				{
    193 					/* Eat the parameter */
    194 					while (*pbBuff && *pbBuff != '}')
    195 						pbBuff++;
    196 					lastwascf = lastwascf0 = 0;
    197 				}
    198 				if (!strcmp(cmd, "colortbl"))
    199 				{
    200 					char color[128];
    201 					int k = 0, m = 1;
    202 					/* Capture the color table */
    203 					while (*pbBuff && !isalnum(*pbBuff))
    204 						pbBuff++;
    205 					for (; *pbBuff && *pbBuff != '}'; pbBuff++)
    206 					{
    207 						if (*pbBuff == ';')
    208 						{
    209 							color[k]=0;
    210 							if (!strcmp(color, "\\red255\\green255\\blue255"))
    211 								colors[m++] = 0;
    212 							else if (!strcmp(color, "\\red0\\green0\\blue0"))
    213 								colors[m++] = 1;
    214 							else if (!strcmp(color, "\\red0\\green0\\blue127"))
    215 								colors[m++] = 2;
    216 							else if (!strcmp(color, "\\red0\\green147\\blue0"))
    217 								colors[m++] = 3;
    218 							else if (!strcmp(color, "\\red255\\green0\\blue0"))
    219 								colors[m++] = 4;
    220 							else if (!strcmp(color, "\\red127\\green0\\blue0"))
    221 								colors[m++] = 5;
    222 							else if (!strcmp(color, "\\red156\\green0\\blue156"))
    223 								colors[m++] = 6;
    224 							else if (!strcmp(color, "\\red252\\green127\\blue0"))
    225 								colors[m++] = 7;
    226 							else if (!strcmp(color, "\\red255\\green255\\blue0"))
    227 								colors[m++] = 8;
    228 							else if (!strcmp(color, "\\red0\\green252\\blue0"))
    229 								colors[m++] = 9;
    230 							else if (!strcmp(color, "\\red0\\green147\\blue147"))
    231 								colors[m++] = 10;
    232 							else if (!strcmp(color, "\\red0\\green255\\blue255"))
    233 								colors[m++] = 11;
    234 							else if (!strcmp(color, "\\red0\\green0\\blue252"))
    235 								colors[m++] = 12;
    236 							else if (!strcmp(color, "\\red255\\green0\\blue255"))
    237 								colors[m++] = 13;
    238 							else if (!strcmp(color, "\\red127\\green127\\blue127"))
    239 								colors[m++] = 14;
    240 							else if (!strcmp(color, "\\red210\\green210\\blue210")) 
    241 								colors[m++] = 15;
    242 							k=0;
    243 						}
    244 						else
    245 							color[k++] = *pbBuff;
    246 					}
    247 					lastwascf = lastwascf0 = 0;
    248 				}
    249 				else if (!strcmp(cmd, "tab"))
    250 				{
    251 					buffer[i++] = '\t';
    252 					lastwascf = lastwascf0 = 0;
    253 				}
    254 				else if (!strcmp(cmd, "par"))
    255 				{
    256 					if (bold || uline || incolor || inbg)
    257 						buffer[i++] = '\17';
    258 					buffer[i++] = '\r';
    259 					buffer[i++] = '\n';
    260 					if (!*(pbBuff+3) || *(pbBuff+3) != '}')
    261 					{
    262 						if (bold)
    263 							buffer[i++] = '\2';
    264 						if (uline)
    265 							buffer[i++] = '\37';
    266 						if (incolor)
    267 						{
    268 							buffer[i++] = '\3';
    269 							strcat(buffer, TextColors->color);
    270 							i += strlen(TextColors->color);
    271 							if (inbg)
    272 							{
    273 								buffer[i++] = ',';
    274 								strcat(buffer, BgColors->color);
    275 								i += strlen(BgColors->color);
    276 							}
    277 						}
    278 						else if (inbg) 
    279 						{
    280 							buffer[i++] = '\3';
    281 							buffer[i++] = '0';
    282 							buffer[i++] = '1';
    283 							buffer[i++] = ',';
    284 							strcat(buffer, BgColors->color);
    285 							i += strlen(BgColors->color);
    286 						}
    287 					}
    288 				}
    289 				else if (!strcmp(cmd, "b"))
    290 				{
    291 					bold = 1;
    292 					buffer[i++] = '\2';
    293 					lastwascf = lastwascf0 = 0;
    294 				}
    295 				else if (!strcmp(cmd, "b0"))
    296 				{
    297 					bold = 0;
    298 					buffer[i++] = '\2';
    299 					lastwascf = lastwascf0 = 0;
    300 				}
    301 				else if (!strcmp(cmd, "ul"))
    302 				{
    303 					uline = 1;
    304 					buffer[i++] = '\37';
    305 					lastwascf = lastwascf0 = 0;
    306 				}
    307 				else if (!strcmp(cmd, "ulnone"))
    308 				{
    309 					uline = 0;
    310 					buffer[i++] = '\37';
    311 					lastwascf = lastwascf0 = 0;
    312 				}
    313 				else if (!strcmp(cmd, "cf0"))
    314 				{
    315 					lastwascf0 = 1;
    316 					lastwascf = 0;
    317 				}
    318 				else if (!strcmp(cmd, "highlight0"))
    319 				{
    320 					inbg = 0;
    321 					ColorPop(&BgColors);
    322 					buffer[i++] = '\3';
    323 					if (lastwascf0)
    324 					{
    325 						incolor = 0;
    326 						ColorPop(&TextColors);
    327 						lastwascf0 = 0;
    328 					}
    329 					else if (incolor)
    330 					{
    331 						strcat(buffer, TextColors->color);
    332 						i += strlen(TextColors->color);
    333 						buffer[i++] = ',';
    334 						buffer[i++] = '0';
    335 						buffer[i++] = '0';
    336 					}
    337 					lastwascf = lastwascf0 = 0;
    338 				}
    339 				else if (!strncmp(cmd, "cf", 2))
    340 				{
    341 					unsigned char number[3];
    342 					int num;
    343 					incolor = 1;
    344 					strcpy(number, &cmd[2]);
    345 					num = atoi(number);
    346 					buffer[i++] = '\3';
    347 					if (colors[num] < 10)
    348 						sprintf(number, "0%d", colors[num]);
    349 					else
    350 						sprintf(number, "%d", colors[num]);
    351 					ColorPush(number, &TextColors);
    352 					strcat(buffer,number);
    353 					i += strlen(number);
    354 					lastwascf = 1;
    355 					lastwascf0 = 0;
    356 				}
    357 				else if (!strncmp(cmd, "highlight", 9))
    358 				{
    359 					int num;
    360 					unsigned char number[3];
    361 					inbg = 1;
    362 					num = atoi(&cmd[9]);
    363 					if (colors[num] < 10)
    364 						sprintf(number, "0%d", colors[num]);
    365 					else
    366 						sprintf(number, "%d", colors[num]);
    367 					if (incolor && !lastwascf)
    368 					{
    369 						buffer[i++] = '\3';
    370 						strcat(buffer, TextColors->color);
    371 						i += strlen(TextColors->color);
    372 					}
    373 					else if (!incolor)
    374 					{
    375 						buffer[i++] = '\3';
    376 						buffer[i++] = '0';
    377 						buffer[i++] = '1';
    378 					}
    379 					buffer[i++] = ',';
    380 					strcat(buffer, number);
    381 					i += strlen(number);
    382 					ColorPush(number, &BgColors);
    383 					lastwascf = lastwascf0 = 0;
    384 				}
    385 				else
    386 					lastwascf = lastwascf0 = 0;
    387 
    388 				if (lastwascf0 && incolor)
    389 				{
    390 					incolor = 0;
    391 					ColorPop(&TextColors);
    392 					buffer[i++] = '\3';
    393 				}
    394 			}
    395 		}
    396 		else
    397 		{
    398 			lastwascf = lastwascf0 = 0;
    399 			buffer[i++] = *pbBuff;
    400 		}
    401 				
    402 	}
    403 	write(fd, buffer, i);
    404 	close(fd);
    405 	ColorEmpty(&TextColors);
    406 	ColorEmpty(&BgColors);
    407 	return 0;
    408 }
    409 
    410 /* Determines the size of the buffer needed to convert IRC codes to RTF
    411  * Parameters:
    412  *  buffer - The input buffer with IRC codes
    413  * Returns:
    414  *  The lenght of the buffer needed to store the RTF translation
    415  */
    416 int CountRTFSize(unsigned char *buffer) {
    417 	int size = 0;
    418 	char bold = 0, uline = 0, incolor = 0, inbg = 0, reverse = 0;
    419 	char *buf = buffer;
    420 
    421 	for (; *buf; buf++) 
    422 	{
    423 		if (*buf == '{' || *buf == '}' || *buf == '\\')
    424 			size++;
    425 		else if (*buf == '\r')
    426 		{
    427 			if (*(buf+1) && *(buf+1) == '\n')
    428 			{
    429 				buf++;
    430 				if (bold)
    431 					size += 3;
    432 				if (uline)
    433 					size += 7;
    434 				if (incolor && !reverse)
    435 					size += 4;
    436 				if (inbg && !reverse)
    437 					size += 11;
    438 				if (reverse)
    439 					size += 15;
    440 				if (bold || uline || incolor || inbg || reverse)
    441 					size++;
    442 				bold = uline = incolor = inbg = reverse = 0;
    443 				size +=6;
    444 				continue;
    445 			}
    446 		}
    447 		else if (*buf == '\n')
    448 		{
    449 			if (bold)
    450 				size += 3;
    451 			if (uline)
    452 				size += 7;
    453 			if (incolor && !reverse)
    454 				size += 4;
    455 			if (inbg && !reverse)
    456 				size += 11;
    457 			if (reverse)
    458 				size += 15;
    459 			if (bold || uline || incolor || inbg || reverse)
    460 				size++;
    461 			bold = uline = incolor = inbg = reverse = 0;
    462 			size +=6;
    463 			continue;	
    464 		}
    465 		else if (*buf == '\2')
    466 		{
    467 			if (bold)
    468 				size += 4;
    469 			else
    470 				size += 3;
    471 			bold = !bold;
    472 			continue;
    473 		}
    474 		else if (*buf == '\3' && reverse)
    475 		{
    476 			if (*(buf+1) && isdigit(*(buf+1)))
    477 			{
    478 				++buf;
    479 				if (*(buf+1) && isdigit(*(buf+1)))
    480 					++buf;
    481 				if (*(buf+1) && *(buf+1) == ',')
    482 				{
    483 					if (*(buf+2) && isdigit(*(buf+2)))
    484 					{
    485 						buf+=2;
    486 						if (*(buf+1) && isdigit(*(buf+1)))
    487 							++buf;
    488 					}
    489 				}
    490 			}
    491 			continue;
    492 		}
    493 		else if (*buf == '\3' && !reverse)
    494 		{
    495 			size += 3;
    496 			if (*(buf+1) && !isdigit(*(buf+1)))
    497 			{
    498 				incolor = 0;
    499 				size++;
    500 				if (inbg)
    501 				{
    502 					inbg = 0;
    503 					size += 11;
    504 				}
    505 			}
    506 			else if (*(buf+1))
    507 			{
    508 				unsigned char color[3];
    509 				int number;
    510 				color[0] = *(++buf);
    511 				color[1] = 0;
    512 				if (*(buf+1) && isdigit(*(buf+1)))
    513 					color[1] = *(++buf);
    514 				color[2] = 0;
    515 				number = atoi(color);
    516 				if (number == 99 || number == 1) 
    517 					size += 2;
    518 				else if (number == 0) 
    519 					size++;
    520 				else  {
    521 					number %= 16;
    522 					_itoa(number, color, 10);
    523 					size += strlen(color);
    524 				}
    525 				color[2] = 0;
    526 				number = atoi(color);
    527 				if (*(buf+1) && *(buf+1) == ',')
    528 				{
    529 					if (*(buf+2) && isdigit(*(buf+2)))
    530 					{
    531 						size += 10;
    532 						buf++;
    533 						color[0] = *(++buf);
    534 						color[1] = 0;
    535 						if (*(buf+1) && isdigit(*(buf+1)))
    536 							color[1] = *(++buf);
    537 						color[2] = 0;
    538 						number = atoi(color);
    539 						if (number == 1)
    540 							size += 2;
    541 						else if (number == 0 || number == 99)
    542 							size++;
    543 						else
    544 						{
    545 							number %= 16;
    546 							_itoa(number, color, 10);
    547 							size += strlen(color);
    548 						}
    549 						inbg = 1;
    550 					}
    551 				}
    552 				incolor = 1;
    553 			}
    554 			size++;
    555 			continue;
    556 		}
    557 		else if (*buf == '\17')
    558 		{
    559 			if (bold)
    560 				size += 3;
    561 			if (uline)
    562 				size += 7;
    563 			if (incolor && !reverse)
    564 				size += 4;
    565 			if (inbg && !reverse)
    566 				size += 11;
    567 			if (reverse)
    568 				size += 15;
    569 			if (bold || uline || incolor || inbg || reverse)
    570 				size++;
    571 			bold = uline = incolor = inbg = reverse = 0;
    572 			continue;
    573 		}
    574 		else if (*buf == '\26')
    575 		{
    576 			if (reverse)
    577 				size += 16;
    578 			else
    579 				size += 17;
    580 			reverse = !reverse;
    581 			continue;
    582 		}
    583 		else if (*buf == '\37')
    584 		{
    585 			if (uline)
    586 				size += 8;
    587 			else
    588 				size += 4;
    589 			uline = !uline;
    590 			continue;
    591 		}
    592 		size++;
    593 	}			
    594 	size += strlen("{\\rtf1\\ansi\\ansicpg1252\\deff0{\\fonttbl{\\f0\\fmodern\\fprq1\\"
    595 		"fcharset0 Fixedsys;}}\r\n"
    596 		MIRC_COLORS
    597 		"\\viewkind4\\uc1\\pard\\lang1033\\f0\\fs20")+1;
    598 	return (size);
    599 }
    600 
    601 /* Converts a string containing IRC codes to RTF
    602  * Parameters:
    603  *  buffer - The input buffer containing IRC codes
    604  *  string - The output buffer in RTF
    605  */
    606 void IRCToRTF(unsigned char *buffer, unsigned char *string) 
    607 {
    608 	unsigned char *tmp;
    609 	int i = 0;
    610 	short bold = 0, uline = 0, incolor = 0, inbg = 0, reverse = 0;
    611 	sprintf(string, "{\\rtf1\\ansi\\ansicpg1252\\deff0{\\fonttbl{\\f0\\fmodern\\fprq1\\"
    612 		"fcharset0 Fixedsys;}}\r\n"
    613 		MIRC_COLORS
    614 		"\\viewkind4\\uc1\\pard\\lang1033\\f0\\fs20");
    615 	i = strlen(string);
    616 	for (tmp = buffer; *tmp; tmp++)
    617 	{
    618 		if (*tmp == '{')
    619 		{
    620 			strcat(string, "\\{");
    621 			i+=2;
    622 			continue;
    623 		}
    624 		else if (*tmp == '}')
    625 		{
    626 			strcat(string, "\\}");
    627 			i+=2;
    628 			continue;
    629 		}
    630 		else if (*tmp == '\\')
    631 		{
    632 			strcat(string, "\\\\");
    633 			i+=2;
    634 			continue;
    635 		}
    636 		else if (*tmp == '\r')
    637 		{
    638 			if (*(tmp+1) && *(tmp+1) == '\n')
    639 			{
    640 				tmp++;
    641 				if (bold)
    642 				{
    643 					strcat(string, "\\b0 ");
    644 					i+=3;
    645 				}
    646 				if (uline)
    647 				{
    648 					strcat(string, "\\ulnone");
    649 					i+=7;
    650 				}
    651 				if (incolor && !reverse)
    652 				{
    653 					strcat(string, "\\cf0");
    654 					i+=4;
    655 				}
    656 				if (inbg && !reverse)
    657 				{
    658 					strcat(string, "\\highlight0");
    659 					i +=11;
    660 				}
    661 				if (reverse) {
    662 					strcat(string, "\\cf0\\highlight0");
    663 					i += 15;
    664 				}
    665 				if (bold || uline || incolor || inbg || reverse)
    666 					string[i++] = ' ';
    667 				bold = uline = incolor = inbg = reverse = 0;
    668 				strcat(string, "\\par\r\n");
    669 				i +=6;
    670 			}
    671 			else
    672 				string[i++]='\r';
    673 			continue;
    674 		}
    675 		else if (*tmp == '\n')
    676 		{
    677 			if (bold)
    678 			{
    679 				strcat(string, "\\b0 ");
    680 				i+=3;
    681 			}
    682 			if (uline)
    683 			{
    684 				strcat(string, "\\ulnone");
    685 				i+=7;
    686 			}
    687 			if (incolor && !reverse)
    688 			{
    689 				strcat(string, "\\cf0");
    690 				i+=4;
    691 			}
    692 			if (inbg && !reverse)
    693 			{
    694 				strcat(string, "\\highlight0");
    695 				i +=11;
    696 			}
    697 			if (reverse) {
    698 				strcat(string, "\\cf0\\highlight0");
    699 				i += 15;
    700 			}
    701 			if (bold || uline || incolor || inbg || reverse)
    702 				string[i++] = ' ';
    703 			bold = uline = incolor = inbg = reverse = 0;
    704 			strcat(string, "\\par\r\n");
    705 			i +=6;
    706 			continue;
    707 		}
    708 		else if (*tmp == '\2')
    709 		{
    710 			if (bold)
    711 			{
    712 				strcat(string, "\\b0 ");
    713 				i+=4;
    714 			}
    715 			else
    716 			{
    717 				strcat(string, "\\b ");
    718 				i+=3;
    719 			}
    720 			bold = !bold;
    721 			continue;
    722 		}
    723 		else if (*tmp == '\3' && reverse)
    724 		{
    725 			if (*(tmp+1) && isdigit(*(tmp+1)))
    726 			{
    727 				++tmp;
    728 				if (*(tmp+1) && isdigit(*(tmp+1)))
    729 					++tmp;
    730 				if (*(tmp+1) && *(tmp+1) == ',')
    731 				{
    732 					if (*(tmp+2) && isdigit(*(tmp+2)))
    733 					{
    734 						tmp+=2;
    735 						if (*(tmp+1) && isdigit(*(tmp+1)))
    736 							++tmp;
    737 					}
    738 				}
    739 			}
    740 			continue;
    741 		}
    742 		else if (*tmp == '\3' && !reverse)
    743 		{
    744 			strcat(string, "\\cf");
    745 			i += 3;
    746 			if (*(tmp+1) && !isdigit(*(tmp+1)))
    747 			{
    748 				incolor = 0;
    749 				string[i++] = '0';
    750 				if (inbg)
    751 				{
    752 					inbg = 0;
    753 					strcat(string, "\\highlight0");
    754 					i += 11;
    755 				}
    756 			}
    757 			else if (*(tmp+1))
    758 			{
    759 				unsigned char color[3];
    760 				int number;
    761 				color[0] = *(++tmp);
    762 				color[1] = 0;
    763 				if (*(tmp+1) && isdigit(*(tmp+1)))
    764 					color[1] = *(++tmp);
    765 				color[2] = 0;
    766 				number = atoi(color);
    767 				if (number == 99 || number == 1)
    768 				{
    769 					strcat(string, "16"); 
    770 					i += 2;
    771 				}
    772 				else if (number == 0) 
    773 				{
    774 					strcat(string, "1");
    775 					i++;
    776 				}
    777 				else
    778 				{
    779 					number %= 16;
    780 					_itoa(number, color, 10);
    781 					strcat(string, color);
    782 					i += strlen(color);
    783 				}
    784 				if (*(tmp+1) && *(tmp+1) == ',')
    785 				{
    786 					if (*(tmp+2) && isdigit(*(tmp+2)))
    787 					{
    788 						strcat(string, "\\highlight");
    789 						i += 10;
    790 						tmp++;
    791 						color[0] = *(++tmp);
    792 						color[1] = 0;
    793 						if (*(tmp+1) && isdigit(*(tmp+1)))
    794 							color[1] = *(++tmp);
    795 						color[2] = 0;
    796 						number = atoi(color);
    797 						if (number == 1)
    798 						{
    799 							strcat(string, "16");
    800 							i += 2;
    801 						}
    802 						else if (number == 0 || number == 99)
    803 							string[i++] = '1';
    804 						else
    805 						{
    806 							number %= 16;
    807 							_itoa(number, color, 10);
    808 							strcat(string,color);
    809 							i += strlen(color);
    810 						}
    811 						inbg = 1;
    812 					}
    813 				}
    814 				incolor=1;
    815 			}
    816 			string[i++] = ' ';
    817 			continue;
    818 		}
    819 		else if (*tmp == '\17') {
    820 			if (uline) {
    821 				strcat(string, "\\ulnone");
    822 				i += 7;
    823 			}
    824 			if (bold) {
    825 				strcat(string, "\\b0");
    826 				i += 3;
    827 			}
    828 			if (incolor && !reverse) {
    829 				strcat(string, "\\cf0");
    830 				i += 4;
    831 			}
    832 			if (inbg && !reverse)
    833 			{
    834 				strcat(string, "\\highlight0");
    835 				i += 11;
    836 			}
    837 			if (reverse) {
    838 				strcat(string, "\\cf0\\highlight0");
    839 				i += 15;
    840 			}
    841 			if (uline || bold || incolor || inbg || reverse)
    842 				string[i++] = ' ';
    843 			uline = bold = incolor = inbg = reverse = 0;
    844 			continue;
    845 		}
    846 		else if (*tmp == '\26')
    847 		{
    848 			if (reverse)
    849 			{
    850 				strcat(string, "\\cf0\\highlight0 ");
    851 				i += 16;
    852 			}
    853 			else
    854 			{
    855 				strcat(string, "\\cf1\\highlight16 ");
    856 				i += 17;
    857 			}
    858 			reverse = !reverse;
    859 			continue;
    860 		}
    861 
    862 		else if (*tmp == '\37') {
    863 			if (uline) {
    864 				strcat(string, "\\ulnone ");
    865 				i += 8;
    866 			}
    867 			else {
    868 				strcat(string, "\\ul ");
    869 				i += 4;
    870 			}
    871 			uline = !uline;
    872 			continue;
    873 		}
    874 		string[i++] = *tmp;
    875 	}
    876 	strcat(string, "}");
    877 	return;
    878 }