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