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