Port things from MSN to WLM plugin:
[kdenetwork.git] / kopete / protocols / groupwise / libgroupwise / rtf.cc
bloba47ff5799a70a138ad6775546fd4440db44591b1
1 #line 2 "rtf.cc"
3 #line 4 "rtf.cc"
5 #define YY_INT_ALIGNED short int
7 /* A lexical scanner generated by flex */
9 #define FLEX_SCANNER
10 #define YY_FLEX_MAJOR_VERSION 2
11 #define YY_FLEX_MINOR_VERSION 5
12 #define YY_FLEX_SUBMINOR_VERSION 31
13 #if YY_FLEX_SUBMINOR_VERSION > 0
14 #define FLEX_BETA
15 #endif
17 /* First, we deal with platform-specific or compiler-specific issues. */
19 /* begin standard C headers. */
20 #include <stdio.h>
21 #include <string.h>
22 #include <errno.h>
23 #include <stdlib.h>
25 /* end standard C headers. */
27 /* flex integer type definitions */
29 #ifndef FLEXINT_H
30 #define FLEXINT_H
32 /* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
34 #if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
35 #include <inttypes.h>
36 typedef int8_t flex_int8_t;
37 typedef uint8_t flex_uint8_t;
38 typedef int16_t flex_int16_t;
39 typedef uint16_t flex_uint16_t;
40 typedef int32_t flex_int32_t;
41 typedef uint32_t flex_uint32_t;
42 #else
43 typedef signed char flex_int8_t;
44 typedef short int flex_int16_t;
45 typedef int flex_int32_t;
46 typedef unsigned char flex_uint8_t;
47 typedef unsigned short int flex_uint16_t;
48 typedef unsigned int flex_uint32_t;
49 #endif /* ! C99 */
51 /* Limits of integral types. */
52 #ifndef INT8_MIN
53 #define INT8_MIN (-128)
54 #endif
55 #ifndef INT16_MIN
56 #define INT16_MIN (-32767-1)
57 #endif
58 #ifndef INT32_MIN
59 #define INT32_MIN (-2147483647-1)
60 #endif
61 #ifndef INT8_MAX
62 #define INT8_MAX (127)
63 #endif
64 #ifndef INT16_MAX
65 #define INT16_MAX (32767)
66 #endif
67 #ifndef INT32_MAX
68 #define INT32_MAX (2147483647)
69 #endif
70 #ifndef UINT8_MAX
71 #define UINT8_MAX (255U)
72 #endif
73 #ifndef UINT16_MAX
74 #define UINT16_MAX (65535U)
75 #endif
76 #ifndef UINT32_MAX
77 #define UINT32_MAX (4294967295U)
78 #endif
80 #endif /* ! FLEXINT_H */
82 #ifdef __cplusplus
84 /* The "const" storage-class-modifier is valid. */
85 #define YY_USE_CONST
87 #else /* ! __cplusplus */
89 #if __STDC__
91 #define YY_USE_CONST
93 #endif /* __STDC__ */
94 #endif /* ! __cplusplus */
96 #ifdef YY_USE_CONST
97 #define yyconst const
98 #else
99 #define yyconst
100 #endif
102 /* Returned upon end-of-file. */
103 #define YY_NULL 0
105 /* Promotes a possibly negative, possibly signed char to an unsigned
106 * integer for use as an array index. If the signed char is negative,
107 * we want to instead treat it as an 8-bit unsigned char, hence the
108 * double cast.
110 #define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
112 /* Enter a start condition. This macro really ought to take a parameter,
113 * but we do it the disgusting crufty way forced on us by the ()-less
114 * definition of BEGIN.
116 #define BEGIN (yy_start) = 1 + 2 *
118 /* Translate the current start state into a value that can be later handed
119 * to BEGIN to return to the state. The YYSTATE alias is for lex
120 * compatibility.
122 #define YY_START (((yy_start) - 1) / 2)
123 #define YYSTATE YY_START
125 /* Action number for EOF rule of a given start state. */
126 #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
128 /* Special action meaning "start processing a new file". */
129 #define YY_NEW_FILE rtfrestart(rtfin )
131 #define YY_END_OF_BUFFER_CHAR 0
133 /* Size of default input buffer. */
134 #ifndef YY_BUF_SIZE
135 #define YY_BUF_SIZE 16384
136 #endif
138 #ifndef YY_TYPEDEF_YY_BUFFER_STATE
139 #define YY_TYPEDEF_YY_BUFFER_STATE
140 typedef struct yy_buffer_state *YY_BUFFER_STATE;
141 #endif
143 extern int rtfleng;
145 extern FILE *rtfin, *rtfout;
147 #define EOB_ACT_CONTINUE_SCAN 0
148 #define EOB_ACT_END_OF_FILE 1
149 #define EOB_ACT_LAST_MATCH 2
151 #define YY_LESS_LINENO(n)
153 /* Return all but the first "n" matched characters back to the input stream. */
154 #define yyless(n) \
155 do \
157 /* Undo effects of setting up rtftext. */ \
158 int yyless_macro_arg = (n); \
159 YY_LESS_LINENO(yyless_macro_arg);\
160 *yy_cp = (yy_hold_char); \
161 YY_RESTORE_YY_MORE_OFFSET \
162 (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
163 YY_DO_BEFORE_ACTION; /* set up rtftext again */ \
165 while ( 0 )
167 #define unput(c) yyunput( c, (yytext_ptr) )
169 /* The following is because we cannot portably get our hands on size_t
170 * (without autoconf's help, which isn't available because we want
171 * flex-generated scanners to compile on their own).
174 #ifndef YY_TYPEDEF_YY_SIZE_T
175 #define YY_TYPEDEF_YY_SIZE_T
176 typedef unsigned int yy_size_t;
177 #endif
179 #ifndef YY_STRUCT_YY_BUFFER_STATE
180 #define YY_STRUCT_YY_BUFFER_STATE
181 struct yy_buffer_state
183 FILE *yy_input_file;
185 char *yy_ch_buf; /* input buffer */
186 char *yy_buf_pos; /* current position in input buffer */
188 /* Size of input buffer in bytes, not including room for EOB
189 * characters.
191 yy_size_t yy_buf_size;
193 /* Number of characters read into yy_ch_buf, not including EOB
194 * characters.
196 int yy_n_chars;
198 /* Whether we "own" the buffer - i.e., we know we created it,
199 * and can realloc() it to grow it, and should free() it to
200 * delete it.
202 int yy_is_our_buffer;
204 /* Whether this is an "interactive" input source; if so, and
205 * if we're using stdio for input, then we want to use getc()
206 * instead of fread(), to make sure we stop fetching input after
207 * each newline.
209 int yy_is_interactive;
211 /* Whether we're considered to be at the beginning of a line.
212 * If so, '^' rules will be active on the next match, otherwise
213 * not.
215 int yy_at_bol;
217 int yy_bs_lineno; /**< The line count. */
218 int yy_bs_column; /**< The column count. */
220 /* Whether to try to fill the input buffer when we reach the
221 * end of it.
223 int yy_fill_buffer;
225 int yy_buffer_status;
227 #define YY_BUFFER_NEW 0
228 #define YY_BUFFER_NORMAL 1
229 /* When an EOF's been seen but there's still some text to process
230 * then we mark the buffer as YY_EOF_PENDING, to indicate that we
231 * shouldn't try reading from the input source any more. We might
232 * still have a bunch of tokens to match, though, because of
233 * possible backing-up.
235 * When we actually see the EOF, we change the status to "new"
236 * (via rtfrestart()), so that the user can continue scanning by
237 * just pointing rtfin at a new input file.
239 #define YY_BUFFER_EOF_PENDING 2
242 #endif /* !YY_STRUCT_YY_BUFFER_STATE */
244 /* Stack of input buffers. */
245 static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
246 static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
247 static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
249 /* We provide macros for accessing buffer states in case in the
250 * future we want to put the buffer states in a more general
251 * "scanner state".
253 * Returns the top of the stack, or NULL.
255 #define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
256 ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
257 : NULL)
259 /* Same as previous macro, but useful when we know that the buffer stack is not
260 * NULL or when we need an lvalue. For internal use only.
262 #define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
264 /* yy_hold_char holds the character lost when rtftext is formed. */
265 static char yy_hold_char;
266 static int yy_n_chars; /* number of characters read into yy_ch_buf */
267 int rtfleng;
269 /* Points to current character in buffer. */
270 static char *yy_c_buf_p = (char *) 0;
271 static int yy_init = 1; /* whether we need to initialize */
272 static int yy_start = 0; /* start state number */
274 /* Flag which is used to allow rtfwrap()'s to do buffer switches
275 * instead of setting up a fresh rtfin. A bit of a hack ...
277 static int yy_did_buffer_switch_on_eof;
279 void rtfrestart (FILE *input_file );
280 void rtf_switch_to_buffer (YY_BUFFER_STATE new_buffer );
281 YY_BUFFER_STATE rtf_create_buffer (FILE *file,int size );
282 void rtf_delete_buffer (YY_BUFFER_STATE b );
283 void rtf_flush_buffer (YY_BUFFER_STATE b );
284 void rtfpush_buffer_state (YY_BUFFER_STATE new_buffer );
285 void rtfpop_buffer_state (void );
287 static void rtfensure_buffer_stack (void );
288 static void rtf_load_buffer_state (void );
289 static void rtf_init_buffer (YY_BUFFER_STATE b,FILE *file );
291 #define YY_FLUSH_BUFFER rtf_flush_buffer(YY_CURRENT_BUFFER )
293 YY_BUFFER_STATE rtf_scan_buffer (char *base,yy_size_t size );
294 YY_BUFFER_STATE rtf_scan_string (yyconst char *yy_str );
295 YY_BUFFER_STATE rtf_scan_bytes (yyconst char *bytes,int len );
297 void *rtfalloc (yy_size_t );
298 void *rtfrealloc (void *,yy_size_t );
299 void rtffree (void * );
301 #define yy_new_buffer rtf_create_buffer
303 #define yy_set_interactive(is_interactive) \
305 if ( ! YY_CURRENT_BUFFER ){ \
306 rtfensure_buffer_stack (); \
307 YY_CURRENT_BUFFER_LVALUE = \
308 rtf_create_buffer(rtfin,YY_BUF_SIZE ); \
310 YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
313 #define yy_set_bol(at_bol) \
315 if ( ! YY_CURRENT_BUFFER ){\
316 rtfensure_buffer_stack (); \
317 YY_CURRENT_BUFFER_LVALUE = \
318 rtf_create_buffer(rtfin,YY_BUF_SIZE ); \
320 YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
323 #define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
325 /* Begin user sect3 */
327 typedef unsigned char YY_CHAR;
329 FILE *rtfin = (FILE *) 0, *rtfout = (FILE *) 0;
331 typedef int yy_state_type;
333 extern int rtflineno;
335 int rtflineno = 1;
337 extern char *rtftext;
338 #define yytext_ptr rtftext
340 static yy_state_type yy_get_previous_state (void );
341 static yy_state_type yy_try_NUL_trans (yy_state_type current_state );
342 static int yy_get_next_buffer (void );
343 static void yy_fatal_error (yyconst char msg[] );
345 /* Done after the current pattern has been matched and before the
346 * corresponding action - sets up rtftext.
348 #define YY_DO_BEFORE_ACTION \
349 (yytext_ptr) = yy_bp; \
350 rtfleng = (size_t) (yy_cp - yy_bp); \
351 (yy_hold_char) = *yy_cp; \
352 *yy_cp = '\0'; \
353 (yy_c_buf_p) = yy_cp;
355 #define YY_NUM_RULES 10
356 #define YY_END_OF_BUFFER 11
357 /* This struct is not used in this scanner,
358 but its presence is necessary. */
359 struct yy_trans_info
361 flex_int32_t yy_verify;
362 flex_int32_t yy_nxt;
364 static yyconst flex_int16_t yy_accept[33] =
365 { 0,
366 0, 0, 11, 8, 8, 9, 9, 1, 2, 8,
367 0, 0, 5, 3, 5, 0, 0, 5, 5, 5,
368 0, 6, 5, 7, 5, 5, 5, 4, 5, 5,
369 5, 0
372 static yyconst flex_int32_t yy_ec[256] =
373 { 0,
374 1, 1, 1, 1, 1, 1, 1, 1, 1, 2,
375 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
376 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
377 1, 3, 1, 1, 4, 1, 1, 1, 5, 1,
378 1, 1, 1, 1, 1, 1, 1, 6, 6, 6,
379 6, 6, 6, 6, 6, 6, 6, 1, 1, 7,
380 1, 8, 9, 1, 10, 10, 10, 10, 10, 10,
381 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
382 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
383 1, 12, 1, 1, 1, 1, 10, 10, 10, 10,
385 10, 10, 11, 11, 11, 11, 11, 11, 11, 11,
386 11, 11, 11, 11, 11, 11, 13, 11, 11, 11,
387 11, 11, 14, 1, 15, 1, 1, 1, 1, 1,
388 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
389 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
390 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
391 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
392 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
393 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
394 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
396 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
397 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
398 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
399 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
400 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
401 1, 1, 1, 1, 1
404 static yyconst flex_int32_t yy_meta[16] =
405 { 0,
406 1, 1, 2, 1, 1, 2, 3, 4, 1, 2,
407 2, 3, 2, 3, 3
410 static yyconst flex_int16_t yy_base[37] =
411 { 0,
412 0, 14, 45, 0, 0, 39, 25, 59, 59, 0,
413 38, 0, 2, 59, 14, 0, 3, 59, 16, 21,
414 25, 59, 28, 59, 38, 23, 19, 59, 17, 12,
415 5, 59, 47, 51, 1, 55
418 static yyconst flex_int16_t yy_def[37] =
419 { 0,
420 33, 33, 32, 34, 34, 32, 32, 32, 32, 34,
421 32, 32, 35, 32, 35, 36, 32, 32, 32, 32,
422 36, 32, 32, 32, 32, 32, 25, 32, 25, 25,
423 25, 0, 32, 32, 32, 32
426 static yyconst flex_int16_t yy_nxt[75] =
427 { 0,
428 32, 5, 13, 32, 18, 17, 6, 19, 22, 17,
429 19, 7, 22, 8, 9, 5, 18, 31, 18, 20,
430 6, 19, 30, 18, 29, 7, 23, 8, 9, 12,
431 18, 28, 24, 25, 13, 13, 14, 15, 14, 14,
432 26, 16, 11, 27, 32, 32, 28, 4, 4, 4,
433 4, 10, 10, 32, 10, 21, 21, 21, 3, 32,
434 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
435 32, 32, 32, 32
438 static yyconst flex_int16_t yy_chk[75] =
439 { 0,
440 0, 1, 35, 0, 13, 12, 1, 13, 17, 12,
441 31, 1, 17, 1, 1, 2, 15, 30, 19, 15,
442 2, 19, 29, 20, 27, 2, 20, 2, 2, 7,
443 23, 26, 21, 23, 7, 7, 7, 7, 7, 7,
444 25, 11, 6, 25, 3, 0, 25, 33, 33, 33,
445 33, 34, 34, 0, 34, 36, 36, 36, 32, 32,
446 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
447 32, 32, 32, 32
450 static yy_state_type yy_last_accepting_state;
451 static char *yy_last_accepting_cpos;
453 extern int rtf_flex_debug;
454 int rtf_flex_debug = 0;
456 /* The intent behind this definition is that it'll catch
457 * any uses of REJECT which flex missed.
459 #define REJECT reject_used_but_not_detected
460 #define yymore() yymore_used_but_not_detected
461 #define YY_MORE_ADJ 0
462 #define YY_RESTORE_YY_MORE_OFFSET
463 char *rtftext;
464 #line 1 "rtf.ll"
465 #line 2 "rtf.ll"
467 rtf.ll - A simple RTF Parser (Flex code)
469 Copyright (c) 2002 by Vladimir Shutoff <vovan@shutoff.ru> (original code)
470 Copyright (c) 2004 by Thiago S. Barcelos <barcelos@ime.usp.br> (Kopete port)
471 Kopete (c) 2002-2003 by the Kopete developers <kopete-devel@kde.org>
473 *************************************************************************
475 * This program is free software; you can redistribute it and/or modify *
476 * it under the terms of the GNU General Public License as published by *
477 * the Free Software Foundation; either version 2 of the License, or *
478 * (at your option) any later version. *
480 *************************************************************************
482 update rtf.cc:
483 flex -olex.yy.c `test -f rtf.ll || echo './'`rtf.ll
484 sed '/^#/ s|lex.yy\.c|rtf.cc|' lex.yy.c >rtf.cc
485 rm -f lex.yy.c
489 #define UP 1
490 #define DOWN 2
491 #define CMD 3
492 #define TXT 4
493 #define HEX 5
494 #define IMG 6
495 #define UNICODE_CHAR 7
496 #define SKIP 8
497 #define SLASH 9
498 #define S_TXT 10
500 #define YY_NEVER_INTERACTIVE 1
501 #define YY_ALWAYS_INTERACTIVE 0
502 #define YY_MAIN 0
504 #line 505 "rtf.cc"
506 #define INITIAL 0
508 #ifndef YY_NO_UNISTD_H
509 /* Special case for "unistd.h", since it is non-ANSI. We include it way
510 * down here because we want the user's section 1 to have been scanned first.
511 * The user has a chance to override it with an option.
513 #include <unistd.h>
514 #endif
516 #ifndef YY_EXTRA_TYPE
517 #define YY_EXTRA_TYPE void *
518 #endif
520 /* Macros after this point can all be overridden by user definitions in
521 * section 1.
524 #ifndef YY_SKIP_YYWRAP
525 #ifdef __cplusplus
526 extern "C" int rtfwrap (void );
527 #else
528 extern int rtfwrap (void );
529 #endif
530 #endif
532 #ifndef yytext_ptr
533 static void yy_flex_strncpy (char *,yyconst char *,int );
534 #endif
536 #ifdef YY_NEED_STRLEN
537 static int yy_flex_strlen (yyconst char * );
538 #endif
540 #ifndef YY_NO_INPUT
542 #ifdef __cplusplus
543 static int yyinput (void );
544 #else
545 static int input (void );
546 #endif
548 #endif
550 /* Amount of stuff to slurp up with each read. */
551 #ifndef YY_READ_BUF_SIZE
552 #define YY_READ_BUF_SIZE 8192
553 #endif
555 /* Copy whatever the last rule matched to the standard output. */
556 #ifndef ECHO
557 /* This used to be an fputs(), but since the string might contain NUL's,
558 * we now use fwrite().
560 #define ECHO (void) fwrite( rtftext, rtfleng, 1, rtfout )
561 #endif
563 /* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
564 * is returned in "result".
566 #ifndef YY_INPUT
567 #define YY_INPUT(buf,result,max_size) \
568 if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
570 int c = '*'; \
571 size_t n; \
572 for ( n = 0; n < max_size && \
573 (c = getc( rtfin )) != EOF && c != '\n'; ++n ) \
574 buf[n] = (char) c; \
575 if ( c == '\n' ) \
576 buf[n++] = (char) c; \
577 if ( c == EOF && ferror( rtfin ) ) \
578 YY_FATAL_ERROR( "input in flex scanner failed" ); \
579 result = n; \
581 else \
583 errno=0; \
584 while ( (result = fread(buf, 1, max_size, rtfin))==0 && ferror(rtfin)) \
586 if( errno != EINTR) \
588 YY_FATAL_ERROR( "input in flex scanner failed" ); \
589 break; \
591 errno=0; \
592 clearerr(rtfin); \
597 #endif
599 /* No semi-colon after return; correct usage is to write "yyterminate();" -
600 * we don't want an extra ';' after the "return" because that will cause
601 * some compilers to complain about unreachable statements.
603 #ifndef yyterminate
604 #define yyterminate() return YY_NULL
605 #endif
607 /* Number of entries by which start-condition stack grows. */
608 #ifndef YY_START_STACK_INCR
609 #define YY_START_STACK_INCR 25
610 #endif
612 /* Report a fatal error. */
613 #ifndef YY_FATAL_ERROR
614 #define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
615 #endif
617 /* end tables serialization structures and prototypes */
619 /* Default declaration of generated scanner - a define so the user can
620 * easily add parameters.
622 #ifndef YY_DECL
623 #define YY_DECL_IS_OURS 1
625 extern int rtflex (void);
627 #define YY_DECL int rtflex (void)
628 #endif /* !YY_DECL */
630 /* Code executed at the beginning of each rule, after rtftext and rtfleng
631 * have been set up.
633 #ifndef YY_USER_ACTION
634 #define YY_USER_ACTION
635 #endif
637 /* Code executed at the end of each rule. */
638 #ifndef YY_BREAK
639 #define YY_BREAK break;
640 #endif
642 #define YY_RULE_SETUP \
643 YY_USER_ACTION
645 /** The main scanner function which does all the work.
647 YY_DECL
649 register yy_state_type yy_current_state;
650 register char *yy_cp, *yy_bp;
651 register int yy_act;
653 #line 46 "rtf.ll"
656 #line 657 "rtf.cc"
658 if ( (yy_init) )
660 (yy_init) = 0;
662 #ifdef YY_USER_INIT
663 YY_USER_INIT;
664 #endif
666 if ( ! (yy_start) )
667 (yy_start) = 1; /* first start state */
669 if ( ! rtfin )
670 rtfin = stdin;
672 if ( ! rtfout )
673 rtfout = stdout;
675 if ( ! YY_CURRENT_BUFFER ) {
676 rtfensure_buffer_stack ();
677 YY_CURRENT_BUFFER_LVALUE =
678 rtf_create_buffer(rtfin,YY_BUF_SIZE );
681 rtf_load_buffer_state( );
684 while ( 1 ) /* loops until end-of-file is reached */
686 yy_cp = (yy_c_buf_p);
688 /* Support of rtftext. */
689 *yy_cp = (yy_hold_char);
691 /* yy_bp points to the position in yy_ch_buf of the start of
692 * the current run.
694 yy_bp = yy_cp;
696 yy_current_state = (yy_start);
697 yy_match:
700 register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
701 if ( yy_accept[yy_current_state] )
703 (yy_last_accepting_state) = yy_current_state;
704 (yy_last_accepting_cpos) = yy_cp;
706 while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
708 yy_current_state = (int) yy_def[yy_current_state];
709 if ( yy_current_state >= 33 )
710 yy_c = yy_meta[(unsigned int) yy_c];
712 yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
713 ++yy_cp;
715 while ( yy_base[yy_current_state] != 59 );
717 yy_find_action:
718 yy_act = yy_accept[yy_current_state];
719 if ( yy_act == 0 )
720 { /* have to back up */
721 yy_cp = (yy_last_accepting_cpos);
722 yy_current_state = (yy_last_accepting_state);
723 yy_act = yy_accept[yy_current_state];
726 YY_DO_BEFORE_ACTION;
728 do_action: /* This label is used only to access EOF actions. */
730 switch ( yy_act )
731 { /* beginning of action switch */
732 case 0: /* must back up */
733 /* undo the effects of YY_DO_BEFORE_ACTION */
734 *yy_cp = (yy_hold_char);
735 yy_cp = (yy_last_accepting_cpos);
736 yy_current_state = (yy_last_accepting_state);
737 goto yy_find_action;
739 case 1:
740 YY_RULE_SETUP
741 #line 48 "rtf.ll"
742 { return UP; }
743 YY_BREAK
744 case 2:
745 YY_RULE_SETUP
746 #line 49 "rtf.ll"
747 { return DOWN; }
748 YY_BREAK
749 case 3:
750 YY_RULE_SETUP
751 #line 50 "rtf.ll"
752 { return SLASH; }
753 YY_BREAK
754 case 4:
755 YY_RULE_SETUP
756 #line 51 "rtf.ll"
757 { return UNICODE_CHAR; }
758 YY_BREAK
759 case 5:
760 YY_RULE_SETUP
761 #line 52 "rtf.ll"
762 { return CMD; }
763 YY_BREAK
764 case 6:
765 YY_RULE_SETUP
766 #line 53 "rtf.ll"
767 { return HEX; }
768 YY_BREAK
769 case 7:
770 /* rule 7 can match eol */
771 YY_RULE_SETUP
772 #line 54 "rtf.ll"
773 { return IMG; }
774 YY_BREAK
775 case 8:
776 /* rule 8 can match eol */
777 YY_RULE_SETUP
778 #line 55 "rtf.ll"
779 { return TXT; }
780 YY_BREAK
781 case 9:
782 YY_RULE_SETUP
783 #line 56 "rtf.ll"
784 { return TXT; }
785 YY_BREAK
786 case 10:
787 YY_RULE_SETUP
788 #line 57 "rtf.ll"
789 ECHO;
790 YY_BREAK
791 #line 792 "rtf.cc"
792 case YY_STATE_EOF(INITIAL):
793 yyterminate();
795 case YY_END_OF_BUFFER:
797 /* Amount of text matched not including the EOB char. */
798 int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
800 /* Undo the effects of YY_DO_BEFORE_ACTION. */
801 *yy_cp = (yy_hold_char);
802 YY_RESTORE_YY_MORE_OFFSET
804 if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
806 /* We're scanning a new file or input source. It's
807 * possible that this happened because the user
808 * just pointed rtfin at a new source and called
809 * rtflex(). If so, then we have to assure
810 * consistency between YY_CURRENT_BUFFER and our
811 * globals. Here is the right place to do so, because
812 * this is the first action (other than possibly a
813 * back-up) that will match for the new input source.
815 (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
816 YY_CURRENT_BUFFER_LVALUE->yy_input_file = rtfin;
817 YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
820 /* Note that here we test for yy_c_buf_p "<=" to the position
821 * of the first EOB in the buffer, since yy_c_buf_p will
822 * already have been incremented past the NUL character
823 * (since all states make transitions on EOB to the
824 * end-of-buffer state). Contrast this with the test
825 * in input().
827 if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
828 { /* This was really a NUL. */
829 yy_state_type yy_next_state;
831 (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
833 yy_current_state = yy_get_previous_state( );
835 /* Okay, we're now positioned to make the NUL
836 * transition. We couldn't have
837 * yy_get_previous_state() go ahead and do it
838 * for us because it doesn't know how to deal
839 * with the possibility of jamming (and we don't
840 * want to build jamming into it because then it
841 * will run more slowly).
844 yy_next_state = yy_try_NUL_trans( yy_current_state );
846 yy_bp = (yytext_ptr) + YY_MORE_ADJ;
848 if ( yy_next_state )
850 /* Consume the NUL. */
851 yy_cp = ++(yy_c_buf_p);
852 yy_current_state = yy_next_state;
853 goto yy_match;
856 else
858 yy_cp = (yy_c_buf_p);
859 goto yy_find_action;
863 else switch ( yy_get_next_buffer( ) )
865 case EOB_ACT_END_OF_FILE:
867 (yy_did_buffer_switch_on_eof) = 0;
869 if ( rtfwrap( ) )
871 /* Note: because we've taken care in
872 * yy_get_next_buffer() to have set up
873 * rtftext, we can now set up
874 * yy_c_buf_p so that if some total
875 * hoser (like flex itself) wants to
876 * call the scanner after we return the
877 * YY_NULL, it'll still work - another
878 * YY_NULL will get returned.
880 (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
882 yy_act = YY_STATE_EOF(YY_START);
883 goto do_action;
886 else
888 if ( ! (yy_did_buffer_switch_on_eof) )
889 YY_NEW_FILE;
891 break;
894 case EOB_ACT_CONTINUE_SCAN:
895 (yy_c_buf_p) =
896 (yytext_ptr) + yy_amount_of_matched_text;
898 yy_current_state = yy_get_previous_state( );
900 yy_cp = (yy_c_buf_p);
901 yy_bp = (yytext_ptr) + YY_MORE_ADJ;
902 goto yy_match;
904 case EOB_ACT_LAST_MATCH:
905 (yy_c_buf_p) =
906 &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
908 yy_current_state = yy_get_previous_state( );
910 yy_cp = (yy_c_buf_p);
911 yy_bp = (yytext_ptr) + YY_MORE_ADJ;
912 goto yy_find_action;
914 break;
917 default:
918 YY_FATAL_ERROR(
919 "fatal flex scanner internal error--no action found" );
920 } /* end of action switch */
921 } /* end of scanning one token */
922 } /* end of rtflex */
924 /* yy_get_next_buffer - try to read in a new buffer
926 * Returns a code representing an action:
927 * EOB_ACT_LAST_MATCH -
928 * EOB_ACT_CONTINUE_SCAN - continue scanning from current position
929 * EOB_ACT_END_OF_FILE - end of file
931 static int yy_get_next_buffer (void)
933 register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
934 register char *source = (yytext_ptr);
935 register int number_to_move, i;
936 int ret_val;
938 if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
939 YY_FATAL_ERROR(
940 "fatal flex scanner internal error--end of buffer missed" );
942 if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
943 { /* Don't try to fill the buffer, so this is an EOF. */
944 if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
946 /* We matched a single character, the EOB, so
947 * treat this as a final EOF.
949 return EOB_ACT_END_OF_FILE;
952 else
954 /* We matched some text prior to the EOB, first
955 * process it.
957 return EOB_ACT_LAST_MATCH;
961 /* Try to read more data. */
963 /* First move last chars to start of buffer. */
964 number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;
966 for ( i = 0; i < number_to_move; ++i )
967 *(dest++) = *(source++);
969 if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
970 /* don't do the read, it's not guaranteed to return an EOF,
971 * just force an EOF
973 YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
975 else
977 size_t num_to_read =
978 YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
980 while ( num_to_read <= 0 )
981 { /* Not enough room in the buffer - grow it. */
983 /* just a shorter name for the current buffer */
984 YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
986 int yy_c_buf_p_offset =
987 (int) ((yy_c_buf_p) - b->yy_ch_buf);
989 if ( b->yy_is_our_buffer )
991 int new_size = b->yy_buf_size * 2;
993 if ( new_size <= 0 )
994 b->yy_buf_size += b->yy_buf_size / 8;
995 else
996 b->yy_buf_size *= 2;
998 b->yy_ch_buf = (char *)
999 /* Include room in for 2 EOB chars. */
1000 rtfrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 );
1002 else
1003 /* Can't grow it, we don't own it. */
1004 b->yy_ch_buf = 0;
1006 if ( ! b->yy_ch_buf )
1007 YY_FATAL_ERROR(
1008 "fatal error - scanner input buffer overflow" );
1010 (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
1012 num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
1013 number_to_move - 1;
1017 if ( num_to_read > YY_READ_BUF_SIZE )
1018 num_to_read = YY_READ_BUF_SIZE;
1020 /* Read in more data. */
1021 YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
1022 (yy_n_chars), num_to_read );
1024 YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
1027 if ( (yy_n_chars) == 0 )
1029 if ( number_to_move == YY_MORE_ADJ )
1031 ret_val = EOB_ACT_END_OF_FILE;
1032 rtfrestart(rtfin );
1035 else
1037 ret_val = EOB_ACT_LAST_MATCH;
1038 YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
1039 YY_BUFFER_EOF_PENDING;
1043 else
1044 ret_val = EOB_ACT_CONTINUE_SCAN;
1046 (yy_n_chars) += number_to_move;
1047 YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
1048 YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
1050 (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
1052 return ret_val;
1055 /* yy_get_previous_state - get the state just before the EOB char was reached */
1057 static yy_state_type yy_get_previous_state (void)
1059 register yy_state_type yy_current_state;
1060 register char *yy_cp;
1062 yy_current_state = (yy_start);
1064 for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
1066 register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
1067 if ( yy_accept[yy_current_state] )
1069 (yy_last_accepting_state) = yy_current_state;
1070 (yy_last_accepting_cpos) = yy_cp;
1072 while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
1074 yy_current_state = (int) yy_def[yy_current_state];
1075 if ( yy_current_state >= 33 )
1076 yy_c = yy_meta[(unsigned int) yy_c];
1078 yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
1081 return yy_current_state;
1084 /* yy_try_NUL_trans - try to make a transition on the NUL character
1086 * synopsis
1087 * next_state = yy_try_NUL_trans( current_state );
1089 static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state )
1091 register int yy_is_jam;
1092 register char *yy_cp = (yy_c_buf_p);
1094 register YY_CHAR yy_c = 1;
1095 if ( yy_accept[yy_current_state] )
1097 (yy_last_accepting_state) = yy_current_state;
1098 (yy_last_accepting_cpos) = yy_cp;
1100 while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
1102 yy_current_state = (int) yy_def[yy_current_state];
1103 if ( yy_current_state >= 33 )
1104 yy_c = yy_meta[(unsigned int) yy_c];
1106 yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
1107 yy_is_jam = (yy_current_state == 32);
1109 return yy_is_jam ? 0 : yy_current_state;
1112 #ifndef YY_NO_INPUT
1113 #ifdef __cplusplus
1114 static int yyinput (void)
1115 #else
1116 static int input (void)
1117 #endif
1120 int c;
1122 *(yy_c_buf_p) = (yy_hold_char);
1124 if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
1126 /* yy_c_buf_p now points to the character we want to return.
1127 * If this occurs *before* the EOB characters, then it's a
1128 * valid NUL; if not, then we've hit the end of the buffer.
1130 if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
1131 /* This was really a NUL. */
1132 *(yy_c_buf_p) = '\0';
1134 else
1135 { /* need more input */
1136 int offset = (yy_c_buf_p) - (yytext_ptr);
1137 ++(yy_c_buf_p);
1139 switch ( yy_get_next_buffer( ) )
1141 case EOB_ACT_LAST_MATCH:
1142 /* This happens because yy_g_n_b()
1143 * sees that we've accumulated a
1144 * token and flags that we need to
1145 * try matching the token before
1146 * proceeding. But for input(),
1147 * there's no matching to consider.
1148 * So convert the EOB_ACT_LAST_MATCH
1149 * to EOB_ACT_END_OF_FILE.
1152 /* Reset buffer status. */
1153 rtfrestart(rtfin );
1155 /*FALLTHROUGH*/
1157 case EOB_ACT_END_OF_FILE:
1159 if ( rtfwrap( ) )
1160 return EOF;
1162 if ( ! (yy_did_buffer_switch_on_eof) )
1163 YY_NEW_FILE;
1164 #ifdef __cplusplus
1165 return yyinput();
1166 #else
1167 return input();
1168 #endif
1171 case EOB_ACT_CONTINUE_SCAN:
1172 (yy_c_buf_p) = (yytext_ptr) + offset;
1173 break;
1178 c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */
1179 *(yy_c_buf_p) = '\0'; /* preserve rtftext */
1180 (yy_hold_char) = *++(yy_c_buf_p);
1182 return c;
1184 #endif /* ifndef YY_NO_INPUT */
1186 /** Immediately switch to a different input stream.
1187 * @param input_file A readable stream.
1189 * @note This function does not reset the start condition to @c INITIAL .
1191 void rtfrestart (FILE * input_file )
1194 if ( ! YY_CURRENT_BUFFER ){
1195 rtfensure_buffer_stack ();
1196 YY_CURRENT_BUFFER_LVALUE =
1197 rtf_create_buffer(rtfin,YY_BUF_SIZE );
1200 rtf_init_buffer(YY_CURRENT_BUFFER,input_file );
1201 rtf_load_buffer_state( );
1204 /** Switch to a different input buffer.
1205 * @param new_buffer The new input buffer.
1208 void rtf_switch_to_buffer (YY_BUFFER_STATE new_buffer )
1211 /* TODO. We should be able to replace this entire function body
1212 * with
1213 * rtfpop_buffer_state();
1214 * rtfpush_buffer_state(new_buffer);
1216 rtfensure_buffer_stack ();
1217 if ( YY_CURRENT_BUFFER == new_buffer )
1218 return;
1220 if ( YY_CURRENT_BUFFER )
1222 /* Flush out information for old buffer. */
1223 *(yy_c_buf_p) = (yy_hold_char);
1224 YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
1225 YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
1228 YY_CURRENT_BUFFER_LVALUE = new_buffer;
1229 rtf_load_buffer_state( );
1231 /* We don't actually know whether we did this switch during
1232 * EOF (rtfwrap()) processing, but the only time this flag
1233 * is looked at is after rtfwrap() is called, so it's safe
1234 * to go ahead and always set it.
1236 (yy_did_buffer_switch_on_eof) = 1;
1239 static void rtf_load_buffer_state (void)
1241 (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
1242 (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
1243 rtfin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
1244 (yy_hold_char) = *(yy_c_buf_p);
1247 /** Allocate and initialize an input buffer state.
1248 * @param file A readable stream.
1249 * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
1251 * @return the allocated buffer state.
1253 YY_BUFFER_STATE rtf_create_buffer (FILE * file, int size )
1255 YY_BUFFER_STATE b;
1257 b = (YY_BUFFER_STATE) rtfalloc(sizeof( struct yy_buffer_state ) );
1258 if ( ! b )
1259 YY_FATAL_ERROR( "out of dynamic memory in rtf_create_buffer()" );
1261 b->yy_buf_size = size;
1263 /* yy_ch_buf has to be 2 characters longer than the size given because
1264 * we need to put in 2 end-of-buffer characters.
1266 b->yy_ch_buf = (char *) rtfalloc(b->yy_buf_size + 2 );
1267 if ( ! b->yy_ch_buf )
1268 YY_FATAL_ERROR( "out of dynamic memory in rtf_create_buffer()" );
1270 b->yy_is_our_buffer = 1;
1272 rtf_init_buffer(b,file );
1274 return b;
1277 /** Destroy the buffer.
1278 * @param b a buffer created with rtf_create_buffer()
1281 void rtf_delete_buffer (YY_BUFFER_STATE b )
1284 if ( ! b )
1285 return;
1287 if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
1288 YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
1290 if ( b->yy_is_our_buffer )
1291 rtffree((void *) b->yy_ch_buf );
1293 rtffree((void *) b );
1296 #ifndef __cplusplus
1297 extern int isatty (int );
1298 #endif /* __cplusplus */
1300 /* Initializes or reinitializes a buffer.
1301 * This function is sometimes called more than once on the same buffer,
1302 * such as during a rtfrestart() or at EOF.
1304 static void rtf_init_buffer (YY_BUFFER_STATE b, FILE * file )
1307 int oerrno = errno;
1309 rtf_flush_buffer(b );
1311 b->yy_input_file = file;
1312 b->yy_fill_buffer = 1;
1314 /* If b is the current buffer, then rtf_init_buffer was _probably_
1315 * called from rtfrestart() or through yy_get_next_buffer.
1316 * In that case, we don't want to reset the lineno or column.
1318 if (b != YY_CURRENT_BUFFER){
1319 b->yy_bs_lineno = 1;
1320 b->yy_bs_column = 0;
1323 b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
1325 errno = oerrno;
1328 /** Discard all buffered characters. On the next scan, YY_INPUT will be called.
1329 * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
1332 void rtf_flush_buffer (YY_BUFFER_STATE b )
1334 if ( ! b )
1335 return;
1337 b->yy_n_chars = 0;
1339 /* We always need two end-of-buffer characters. The first causes
1340 * a transition to the end-of-buffer state. The second causes
1341 * a jam in that state.
1343 b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
1344 b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
1346 b->yy_buf_pos = &b->yy_ch_buf[0];
1348 b->yy_at_bol = 1;
1349 b->yy_buffer_status = YY_BUFFER_NEW;
1351 if ( b == YY_CURRENT_BUFFER )
1352 rtf_load_buffer_state( );
1355 /** Pushes the new state onto the stack. The new state becomes
1356 * the current state. This function will allocate the stack
1357 * if necessary.
1358 * @param new_buffer The new state.
1361 void rtfpush_buffer_state (YY_BUFFER_STATE new_buffer )
1363 if (new_buffer == NULL)
1364 return;
1366 rtfensure_buffer_stack();
1368 /* This block is copied from rtf_switch_to_buffer. */
1369 if ( YY_CURRENT_BUFFER )
1371 /* Flush out information for old buffer. */
1372 *(yy_c_buf_p) = (yy_hold_char);
1373 YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
1374 YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
1377 /* Only push if top exists. Otherwise, replace top. */
1378 if (YY_CURRENT_BUFFER)
1379 (yy_buffer_stack_top)++;
1380 YY_CURRENT_BUFFER_LVALUE = new_buffer;
1382 /* copied from rtf_switch_to_buffer. */
1383 rtf_load_buffer_state( );
1384 (yy_did_buffer_switch_on_eof) = 1;
1387 /** Removes and deletes the top of the stack, if present.
1388 * The next element becomes the new top.
1391 void rtfpop_buffer_state (void)
1393 if (!YY_CURRENT_BUFFER)
1394 return;
1396 rtf_delete_buffer(YY_CURRENT_BUFFER );
1397 YY_CURRENT_BUFFER_LVALUE = NULL;
1398 if ((yy_buffer_stack_top) > 0)
1399 --(yy_buffer_stack_top);
1401 if (YY_CURRENT_BUFFER) {
1402 rtf_load_buffer_state( );
1403 (yy_did_buffer_switch_on_eof) = 1;
1407 /* Allocates the stack if it does not exist.
1408 * Guarantees space for at least one push.
1410 static void rtfensure_buffer_stack (void)
1412 int num_to_alloc;
1414 if (!(yy_buffer_stack)) {
1416 /* First allocation is just for 2 elements, since we don't know if this
1417 * scanner will even need a stack. We use 2 instead of 1 to avoid an
1418 * immediate realloc on the next call.
1420 num_to_alloc = 1;
1421 (yy_buffer_stack) = (struct yy_buffer_state**)rtfalloc
1422 (num_to_alloc * sizeof(struct yy_buffer_state*)
1425 memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
1427 (yy_buffer_stack_max) = num_to_alloc;
1428 (yy_buffer_stack_top) = 0;
1429 return;
1432 if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
1434 /* Increase the buffer to prepare for a possible push. */
1435 int grow_size = 8 /* arbitrary grow size */;
1437 num_to_alloc = (yy_buffer_stack_max) + grow_size;
1438 (yy_buffer_stack) = (struct yy_buffer_state**)rtfrealloc
1439 ((yy_buffer_stack),
1440 num_to_alloc * sizeof(struct yy_buffer_state*)
1443 /* zero only the new slots.*/
1444 memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
1445 (yy_buffer_stack_max) = num_to_alloc;
1449 /** Setup the input buffer state to scan directly from a user-specified character buffer.
1450 * @param base the character buffer
1451 * @param size the size in bytes of the character buffer
1453 * @return the newly allocated buffer state object.
1455 YY_BUFFER_STATE rtf_scan_buffer (char * base, yy_size_t size )
1457 YY_BUFFER_STATE b;
1459 if ( size < 2 ||
1460 base[size-2] != YY_END_OF_BUFFER_CHAR ||
1461 base[size-1] != YY_END_OF_BUFFER_CHAR )
1462 /* They forgot to leave room for the EOB's. */
1463 return 0;
1465 b = (YY_BUFFER_STATE) rtfalloc(sizeof( struct yy_buffer_state ) );
1466 if ( ! b )
1467 YY_FATAL_ERROR( "out of dynamic memory in rtf_scan_buffer()" );
1469 b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
1470 b->yy_buf_pos = b->yy_ch_buf = base;
1471 b->yy_is_our_buffer = 0;
1472 b->yy_input_file = 0;
1473 b->yy_n_chars = b->yy_buf_size;
1474 b->yy_is_interactive = 0;
1475 b->yy_at_bol = 1;
1476 b->yy_fill_buffer = 0;
1477 b->yy_buffer_status = YY_BUFFER_NEW;
1479 rtf_switch_to_buffer(b );
1481 return b;
1484 /** Setup the input buffer state to scan a string. The next call to rtflex() will
1485 * scan from a @e copy of @a str.
1486 * @param str a NUL-terminated string to scan
1488 * @return the newly allocated buffer state object.
1489 * @note If you want to scan bytes that may contain NUL values, then use
1490 * rtf_scan_bytes() instead.
1492 YY_BUFFER_STATE rtf_scan_string (yyconst char * yy_str )
1495 return rtf_scan_bytes(yy_str,strlen(yy_str) );
1498 /** Setup the input buffer state to scan the given bytes. The next call to rtflex() will
1499 * scan from a @e copy of @a bytes.
1500 * @param bytes the byte buffer to scan
1501 * @param len the number of bytes in the buffer pointed to by @a bytes.
1503 * @return the newly allocated buffer state object.
1505 YY_BUFFER_STATE rtf_scan_bytes (yyconst char * bytes, int len )
1507 YY_BUFFER_STATE b;
1508 char *buf;
1509 yy_size_t n;
1510 int i;
1512 /* Get memory for full buffer, including space for trailing EOB's. */
1513 n = len + 2;
1514 buf = (char *) rtfalloc(n );
1515 if ( ! buf )
1516 YY_FATAL_ERROR( "out of dynamic memory in rtf_scan_bytes()" );
1518 for ( i = 0; i < len; ++i )
1519 buf[i] = bytes[i];
1521 buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR;
1523 b = rtf_scan_buffer(buf,n );
1524 if ( ! b )
1525 YY_FATAL_ERROR( "bad buffer in rtf_scan_bytes()" );
1527 /* It's okay to grow etc. this buffer, and we should throw it
1528 * away when we're done.
1530 b->yy_is_our_buffer = 1;
1532 return b;
1535 #ifndef YY_EXIT_FAILURE
1536 #define YY_EXIT_FAILURE 2
1537 #endif
1539 static void yy_fatal_error (yyconst char* msg )
1541 (void) fprintf( stderr, "%s\n", msg );
1542 exit( YY_EXIT_FAILURE );
1545 /* Redefine yyless() so it works in section 3 code. */
1547 #undef yyless
1548 #define yyless(n) \
1549 do \
1551 /* Undo effects of setting up rtftext. */ \
1552 int yyless_macro_arg = (n); \
1553 YY_LESS_LINENO(yyless_macro_arg);\
1554 rtftext[rtfleng] = (yy_hold_char); \
1555 (yy_c_buf_p) = rtftext + yyless_macro_arg; \
1556 (yy_hold_char) = *(yy_c_buf_p); \
1557 *(yy_c_buf_p) = '\0'; \
1558 rtfleng = yyless_macro_arg; \
1560 while ( 0 )
1562 /* Accessor methods (get/set functions) to struct members. */
1564 /** Get the current line number.
1567 int rtfget_lineno (void)
1570 return rtflineno;
1573 /** Get the input stream.
1576 FILE *rtfget_in (void)
1578 return rtfin;
1581 /** Get the output stream.
1584 FILE *rtfget_out (void)
1586 return rtfout;
1589 /** Get the length of the current token.
1592 int rtfget_leng (void)
1594 return rtfleng;
1597 /** Get the current token.
1601 char *rtfget_text (void)
1603 return rtftext;
1606 /** Set the current line number.
1607 * @param line_number
1610 void rtfset_lineno (int line_number )
1613 rtflineno = line_number;
1616 /** Set the input stream. This does not discard the current
1617 * input buffer.
1618 * @param in_str A readable stream.
1620 * @see rtf_switch_to_buffer
1622 void rtfset_in (FILE * in_str )
1624 rtfin = in_str ;
1627 void rtfset_out (FILE * out_str )
1629 rtfout = out_str ;
1632 int rtfget_debug (void)
1634 return rtf_flex_debug;
1637 void rtfset_debug (int bdebug )
1639 rtf_flex_debug = bdebug ;
1642 /* rtflex_destroy is for both reentrant and non-reentrant scanners. */
1643 int rtflex_destroy (void)
1646 /* Pop the buffer stack, destroying each element. */
1647 while(YY_CURRENT_BUFFER){
1648 rtf_delete_buffer(YY_CURRENT_BUFFER );
1649 YY_CURRENT_BUFFER_LVALUE = NULL;
1650 rtfpop_buffer_state();
1653 /* Destroy the stack itself. */
1654 rtffree((yy_buffer_stack) );
1655 (yy_buffer_stack) = NULL;
1657 return 0;
1661 * Internal utility routines.
1664 #ifndef yytext_ptr
1665 static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
1667 register int i;
1668 for ( i = 0; i < n; ++i )
1669 s1[i] = s2[i];
1671 #endif
1673 #ifdef YY_NEED_STRLEN
1674 static int yy_flex_strlen (yyconst char * s )
1676 register int n;
1677 for ( n = 0; s[n]; ++n )
1680 return n;
1682 #endif
1684 void *rtfalloc (yy_size_t size )
1686 return (void *) malloc( size );
1689 void *rtfrealloc (void * ptr, yy_size_t size )
1691 /* The cast to (char *) in the following accommodates both
1692 * implementations that use char* generic pointers, and those
1693 * that use void* generic pointers. It works with the latter
1694 * because both ANSI C and C++ allow castless assignment from
1695 * any pointer type to void*, and deal with argument conversions
1696 * as though doing an assignment.
1698 return (void *) realloc( (char *) ptr, size );
1701 void rtffree (void * ptr )
1703 free( (char *) ptr ); /* see rtfrealloc() for (char *) cast */
1706 #define YYTABLES_NAME "yytables"
1708 #undef YY_NEW_FILE
1709 #undef YY_FLUSH_BUFFER
1710 #undef yy_set_bol
1711 #undef yy_new_buffer
1712 #undef yy_set_interactive
1713 #undef yytext_ptr
1714 #undef YY_DO_BEFORE_ACTION
1716 #ifdef YY_DECL_IS_OURS
1717 #undef YY_DECL_IS_OURS
1718 #undef YY_DECL
1719 #endif
1720 #line 57 "rtf.ll"
1724 #include "rtf2html.h"
1726 void ParStyle::clearFormatting()
1728 // For now, do nothing.
1729 // dir is not a formatting item.
1732 QString RTF2HTML::quoteString(const QString &_str, quoteMode mode)
1734 QString str = _str;
1735 str.replace('&', "&amp;");
1736 str.replace('<', "&lt;");
1737 str.replace('>', "&gt;");
1738 str.replace('\"', "&quot;");
1739 str.remove('\r');
1740 switch (mode){
1741 case quoteHTML:
1742 str.replace(QRegExp("\n"), "<br>\n");
1743 break;
1744 case quoteXML:
1745 str.replace(QRegExp("\n"), "<br/>\n");
1746 break;
1747 default:
1748 break;
1750 QRegExp re(" +");
1751 int len;
1752 int pos = 0;
1754 while ((pos = re.indexIn(str, pos)) != -1) {
1755 len = re.matchedLength();
1757 if (len == 1)
1758 continue;
1759 QString s = " ";
1760 for (int i = 1; i < len; i++)
1761 s += "&nbsp;";
1762 str.replace(pos, len, s);
1764 return str;
1767 RTF2HTML::RTF2HTML()
1768 : cur_level(this)
1770 rtf_ptr = NULL;
1771 bExplicitParagraph = false;
1774 OutTag* RTF2HTML::getTopOutTag(TagEnum tagType)
1776 vector<OutTag>::iterator it, it_end;
1777 for(it = oTags.begin(), it_end = oTags.end(); it != it_end; ++it)
1778 if (it->tag == tagType)
1779 return &(*it);
1780 return NULL;
1783 void RTF2HTML::FlushOutTags()
1785 vector<OutTag>::iterator iter;
1786 for (iter = oTags.begin(); iter != oTags.end(); iter++)
1788 OutTag &t = *iter;
1789 switch (t.tag){
1790 case TAG_FONT_COLOR:
1792 // RTF colors are 1-based; colors[] is a 0-based array.
1793 if (t.param > colors.size() || t.param == 0)
1794 break;
1795 QColor &c = colors[t.param-1];
1796 PrintUnquoted("<span style=\"color:#%02X%02X%02X\">", c.red(), c.green(), c.blue());
1798 break;
1799 case TAG_FONT_SIZE:
1800 PrintUnquoted("<span style=\"font-size:%upt\">", t.param);
1801 break;
1802 case TAG_FONT_FAMILY:
1804 if (t.param > fonts.size() || t.param == 0)
1805 break;
1806 FontDef &f = fonts[t.param-1];
1807 string name = (!f.nonTaggedName.empty()) ? f.nonTaggedName : f.taggedName;
1808 PrintUnquoted("<span style=\"font-family:%s\">", name.c_str());
1810 break;
1811 case TAG_BG_COLOR:{
1812 if (t.param > colors.size() || t.param == 0)
1813 break;
1814 QColor &c = colors[t.param-1];
1815 PrintUnquoted("<span style=\"background-color:#%02X%02X%02X;\">", c.red(), c.green(), c.blue());
1816 break;
1818 case TAG_BOLD:
1819 PrintUnquoted("<b>");
1820 break;
1821 case TAG_ITALIC:
1822 PrintUnquoted("<i>");
1823 break;
1824 case TAG_UNDERLINE:
1825 PrintUnquoted("<u>");
1826 break;
1827 default:
1828 break;
1831 oTags.clear();
1834 // This function will close the already-opened tag 'tag'. It will take
1835 // care of closing the tags which 'tag' contains first (ie. it will unroll
1836 // the stack till the point where 'tag' is).
1837 void Level::resetTag(TagEnum tag)
1839 // A stack which'll keep tags we had to close in order to reach 'tag'.
1840 // After we close 'tag', we will reopen them.
1841 stack<TagEnum> s;
1843 while (p->tags.size() > m_nTagsStartPos){ // Don't go further than the point where this level starts.
1845 TagEnum nTag = p->tags.top();
1847 /* A tag will be located in oTags if it still wasn't printed out.
1848 A tag will get printed out only if necessary (e.g. <I></I> will
1849 be optimized away).
1850 Thus, for each tag we remove from the actual tag stack, we also
1851 try to remove a yet-to-be-printed tag, and only if there are no
1852 yet-to-be-printed tags left, we start closing the tags we pop.
1853 The tags have one space - needed for umlaute (�) and .toUtf8()
1855 if (p->oTags.empty()){
1856 switch (nTag){
1857 case TAG_FONT_COLOR:
1858 case TAG_FONT_SIZE:
1859 case TAG_BG_COLOR:
1860 case TAG_FONT_FAMILY:
1861 p->PrintUnquoted(" </span>");
1862 break;
1863 case TAG_BOLD:
1864 p->PrintUnquoted(" </b>");
1865 break;
1866 case TAG_ITALIC:
1867 p->PrintUnquoted(" </i>");
1868 break;
1869 case TAG_UNDERLINE:
1870 p->PrintUnquoted(" </u>");
1871 break;
1872 default:
1873 break;
1875 }else{
1876 p->oTags.pop_back();
1879 p->tags.pop();
1880 if (nTag == tag) break; // if we reached the tag we were looking to close.
1881 s.push(nTag); // remember to reopen this tag
1884 if (tag == TAG_ALL) return;
1886 while (!s.empty()){
1887 TagEnum nTag = s.top();
1888 switch (nTag){
1889 case TAG_FONT_COLOR:{
1890 unsigned nFontColor = m_nFontColor;
1891 m_nFontColor = 0;
1892 setFontColor(nFontColor);
1893 break;
1895 case TAG_FONT_SIZE:{
1896 unsigned nFontSize = m_nFontSize;
1897 m_nFontSize = 0;
1898 setFontSize(nFontSize);
1899 break;
1901 case TAG_BG_COLOR:{
1902 unsigned nFontBgColor = m_nFontBgColor;
1903 m_nFontBgColor = 0;
1904 setFontBgColor(nFontBgColor);
1905 break;
1907 case TAG_FONT_FAMILY:{
1908 unsigned nFont = m_nFont;
1909 m_nFont = 0;
1910 setFont(nFont);
1911 break;
1913 case TAG_BOLD:{
1914 bool nBold = m_bBold;
1915 m_bBold = false;
1916 setBold(nBold);
1917 break;
1919 case TAG_ITALIC:{
1920 bool nItalic = m_bItalic;
1921 m_bItalic = false;
1922 setItalic(nItalic);
1923 break;
1925 case TAG_UNDERLINE:{
1926 bool nUnderline = m_bUnderline;
1927 m_bUnderline = false;
1928 setUnderline(nUnderline);
1929 break;
1931 default:
1932 break;
1934 s.pop();
1938 Level::Level(RTF2HTML *_p) :
1939 p(_p),
1940 m_bFontTbl(false),
1941 m_bColors(false),
1942 m_bFontName(false),
1943 m_bTaggedFontNameOk(false),
1944 m_nFont(0),
1945 m_nEncoding(0)
1947 m_nTagsStartPos = p->tags.size();
1948 Init();
1951 Level::Level(const Level &l) :
1952 p(l.p),
1953 m_bFontTbl(l.m_bFontTbl),
1954 m_bColors(l.m_bColors),
1955 m_bFontName(false),
1956 m_bTaggedFontNameOk(l.m_bTaggedFontNameOk),
1957 m_nFont(l.m_nFont),
1958 m_nEncoding(l.m_nEncoding)
1960 m_nTagsStartPos = p->tags.size();
1961 Init();
1964 void Level::Init()
1966 m_nFontColor = 0;
1967 m_nFontBgColor = 0;
1968 m_nFontSize = 0;
1969 m_bFontName = false;
1970 m_bBold = false;
1971 m_bItalic = false;
1972 m_bUnderline = false;
1975 void RTF2HTML::PrintUnquoted(const char *str, ...)
1977 char buff[1024];
1978 va_list ap;
1979 va_start(ap, str);
1980 vsnprintf(buff, sizeof(buff), str, ap);
1981 va_end(ap);
1982 sParagraph += buff;
1985 void RTF2HTML::PrintQuoted(const QString &str)
1987 sParagraph += quoteString(str);
1990 void RTF2HTML::FlushParagraph()
1992 if (!bExplicitParagraph || sParagraph.isEmpty())
1993 return;
1996 s += "<p dir=\"";
1997 // Note: Lower-case 'ltr' and 'rtl' are important for Qt.
1998 s += (parStyle.dir == ParStyle::DirRTL ? "rtl" : "ltr");
1999 s += "\">";
2000 s += sParagraph;
2001 s += "</p>";
2004 s += sParagraph;
2005 s += "<br>";
2007 // Clear up the paragraph members
2008 sParagraph = "";
2009 bExplicitParagraph = false;
2012 void Level::setFont(unsigned nFont)
2014 if (nFont <= 0)
2015 return;
2017 if (m_bFontTbl){
2018 if (nFont > p->fonts.size() +1){
2019 // kDebug(14191) << "Invalid font index (" <<
2020 // nFont << ") while parsing font table." << endl;
2021 return;
2023 if (nFont > p->fonts.size()){
2024 FontDef f;
2025 f.charset = 0;
2026 p->fonts.push_back(f);
2028 m_nFont = nFont;
2030 else
2032 if (nFont > p->fonts.size())
2034 // kDebug(14191) << "Invalid font index (" <<
2035 // nFont << ")." << endl;
2036 return;
2038 if (m_nFont == nFont)
2039 return;
2040 m_nFont = nFont;
2041 if (m_nFont) resetTag(TAG_FONT_FAMILY);
2042 m_nEncoding = p->fonts[nFont-1].charset;
2043 p->oTags.push_back(OutTag(TAG_FONT_FAMILY, nFont));
2044 p->PutTag(TAG_FONT_FAMILY);
2048 void Level::setFontName()
2050 // This function is only valid during font table parsing.
2051 if (m_bFontTbl){
2052 if ((m_nFont > 0) && (m_nFont <= p->fonts.size()))
2053 // Be prepared to accept a font name.
2054 m_bFontName = true;
2058 void Level::setEncoding(unsigned nEncoding)
2060 if (m_bFontTbl){
2061 if ((m_nFont > 0) && (m_nFont <= p->fonts.size()))
2062 p->fonts[m_nFont-1].charset = nEncoding;
2063 return;
2065 m_nEncoding = nEncoding;
2068 void Level::setBold(bool bBold)
2070 if (m_bBold == bBold) return;
2071 if (m_bBold) resetTag(TAG_BOLD);
2072 m_bBold = bBold;
2073 if (!m_bBold) return;
2074 p->oTags.push_back(OutTag(TAG_BOLD, 0));
2075 p->PutTag(TAG_BOLD);
2078 void Level::setItalic(bool bItalic)
2080 if (m_bItalic == bItalic) return;
2081 if (m_bItalic) resetTag(TAG_ITALIC);
2082 m_bItalic = bItalic;
2083 if (!m_bItalic) return;
2084 p->oTags.push_back(OutTag(TAG_ITALIC, 0));
2085 p->PutTag(TAG_ITALIC);
2088 void Level::setUnderline(bool bUnderline)
2090 if (m_bUnderline == bUnderline) return;
2091 if (m_bUnderline) resetTag(TAG_UNDERLINE);
2092 m_bUnderline = bUnderline;
2093 if (!m_bUnderline) return;
2094 p->oTags.push_back(OutTag(TAG_UNDERLINE, 0));
2095 p->PutTag(TAG_UNDERLINE);
2098 void Level::setFontColor(unsigned short nColor)
2100 if (m_nFontColor == nColor) return;
2101 if (m_nFontColor) resetTag(TAG_FONT_COLOR);
2102 if (nColor > p->colors.size()) return;
2103 m_nFontColor = nColor;
2104 p->oTags.push_back(OutTag(TAG_FONT_COLOR, m_nFontColor));
2105 p->PutTag(TAG_FONT_COLOR);
2108 void Level::setFontBgColor(unsigned short nColor)
2110 if (m_nFontBgColor == nColor) return;
2111 if (m_nFontBgColor != 0) resetTag(TAG_BG_COLOR);
2112 if (nColor > p->colors.size()) return;
2113 m_nFontBgColor = nColor;
2114 p->oTags.push_back(OutTag(TAG_BG_COLOR, m_nFontBgColor));
2115 p->PutTag(TAG_BG_COLOR);
2118 void Level::setFontSizeHalfPoints(unsigned short nSize)
2120 setFontSize(nSize / 2);
2123 void Level::setFontSize(unsigned short nSize)
2125 if (m_nFontSize == nSize) return;
2126 if (m_nFontSize) resetTag(TAG_FONT_SIZE);
2127 p->oTags.push_back(OutTag(TAG_FONT_SIZE, nSize));
2128 p->PutTag(TAG_FONT_SIZE);
2129 m_nFontSize = nSize;
2132 void Level::startParagraph()
2134 // Whatever tags we have open now, close them.
2135 // We cannot carry let character formatting tags wrap paragraphs,
2136 // since a formatting tag can close at any time and we cannot
2137 // close the paragraph any time we want.
2138 resetTag(TAG_ALL);
2140 // Flush the current paragraph HTML to the document HTML.
2141 p->FlushParagraph();
2143 // Mark this new paragraph as an explicit one (from \par etc.).
2144 p->bExplicitParagraph = true;
2146 // Restore character formatting
2147 p->oTags.push_back(OutTag(TAG_FONT_SIZE, m_nFontSize));
2148 p->PutTag(TAG_FONT_SIZE);
2149 p->oTags.push_back(OutTag(TAG_FONT_COLOR, m_nFontColor));
2150 p->PutTag(TAG_FONT_COLOR);
2151 p->oTags.push_back(OutTag(TAG_FONT_FAMILY, m_nFont));
2152 p->PutTag(TAG_FONT_FAMILY);
2153 if (m_nFontBgColor != 0)
2155 p->oTags.push_back(OutTag(TAG_BG_COLOR, m_nFontBgColor));
2156 p->PutTag(TAG_BG_COLOR);
2158 if (m_bBold)
2160 p->oTags.push_back(OutTag(TAG_BOLD, 0));
2161 p->PutTag(TAG_BOLD);
2163 if (m_bItalic)
2165 p->PutTag(TAG_ITALIC);
2166 p->oTags.push_back(OutTag(TAG_ITALIC, 0));
2168 if (m_bUnderline)
2170 p->oTags.push_back(OutTag(TAG_UNDERLINE, 0));
2171 p->PutTag(TAG_UNDERLINE);
2175 bool Level::isParagraphOpen() const
2177 return p->bExplicitParagraph;
2180 void Level::clearParagraphFormatting()
2182 // implicitly start a paragraph
2183 if (!isParagraphOpen())
2184 startParagraph();
2185 // Since we don't implement any of the paragraph formatting tags (e.g. alignment),
2186 // we don't clean up anything here. Note that \pard does NOT clean character
2187 // formatting (such as font size, font weight, italics...).
2188 p->parStyle.clearFormatting();
2191 void Level::setParagraphDirLTR()
2193 // implicitly start a paragraph
2194 if (!isParagraphOpen())
2195 startParagraph();
2196 p->parStyle.dir = ParStyle::DirLTR;
2199 void Level::setParagraphDirRTL()
2201 // implicitly start a paragraph
2202 if (!isParagraphOpen())
2203 startParagraph();
2204 p->parStyle.dir = ParStyle::DirRTL;
2207 void Level::addLineBreak()
2209 p->PrintUnquoted("<br/>");
2212 void Level::reset()
2214 resetTag(TAG_ALL);
2215 if (m_bColors){
2216 if (m_bColorInit){
2217 QColor c(m_nRed, m_nGreen, m_nBlue);
2218 p->colors.push_back(c);
2219 resetColors();
2221 return;
2225 void Level::setText(const char *str)
2227 if (m_bColors)
2229 reset();
2231 else if (m_bFontTbl)
2233 if ((m_nFont <= 0) || (m_nFont > p->fonts.size()))
2234 return;
2236 FontDef& def = p->fonts[m_nFont-1];
2238 const char *pp = strchr(str, ';');
2239 unsigned size;
2240 if (pp != NULL)
2241 size = (pp - str);
2242 else
2243 size = strlen(str);
2245 if (m_bFontName)
2247 def.nonTaggedName.append(str, size);
2248 // We know we have the entire name
2249 if (pp != NULL)
2250 m_bFontName = false;
2252 else if (!m_bTaggedFontNameOk)
2254 def.taggedName.append(str, size);
2255 if (pp != NULL)
2256 m_bTaggedFontNameOk = true;
2259 else
2261 for (; *str; str++)
2262 if ((unsigned char)(*str) >= ' ') break;
2263 if (!*str) return;
2264 p->FlushOutTags();
2265 text += str;
2269 void Level::flush()
2271 if (text.length() == 0) return;
2272 // TODO: Make encoding work in Kopete
2274 const char *encoding = NULL;
2275 if (m_nEncoding){
2276 for (const ENCODING *c = ICQPlugin::core->encodings; c->language; c++){
2277 if (!c->bMain)
2278 continue;
2279 if ((unsigned)c->rtf_code == m_nEncoding){
2280 encoding = c->codec;
2281 break;
2285 if (encoding == NULL)
2286 encoding = p->encoding;
2288 QTextCodec *codec = ICQClient::_getCodec(encoding);
2290 //p->PrintQuoted(codec->toUnicode(text.c_str(), text.length()));
2291 p->PrintQuoted(text.c_str());
2292 text = "";
2295 const unsigned FONTTBL = 0;
2296 const unsigned COLORTBL = 1;
2297 const unsigned RED = 2;
2298 const unsigned GREEN = 3;
2299 const unsigned BLUE = 4;
2300 const unsigned CF = 5;
2301 const unsigned FS = 6;
2302 const unsigned HIGHLIGHT = 7;
2303 const unsigned PARD = 8;
2304 const unsigned PAR = 9;
2305 const unsigned I = 10;
2306 const unsigned B = 11;
2307 const unsigned UL = 12;
2308 const unsigned F = 13;
2309 const unsigned FCHARSET = 14;
2310 const unsigned FNAME = 15;
2311 const unsigned ULNONE = 16;
2312 const unsigned LTRPAR = 17;
2313 const unsigned RTLPAR = 18;
2314 const unsigned LINE = 19;
2316 static char cmds[] =
2317 "fonttbl\x00"
2318 "colortbl\x00"
2319 "red\x00"
2320 "green\x00"
2321 "blue\x00"
2322 "cf\x00"
2323 "fs\x00"
2324 "highlight\x00"
2325 "pard\x00"
2326 "par\x00"
2327 "i\x00"
2328 "b\x00"
2329 "ul\x00"
2330 "f\x00"
2331 "fcharset\x00"
2332 "fname\x00"
2333 "ulnone\x00"
2334 "ltrpar\x00"
2335 "rtlpar\x00"
2336 "line\x00"
2337 "\x00";
2339 int rtfwrap() { return 1; }
2341 static char h2d(char c)
2343 if ((c >= '0') && (c <= '9'))
2344 return c - '0';
2345 if ((c >= 'A') && (c <= 'F'))
2346 return (c - 'A') + 10;
2347 if ((c >= 'a') && (c <= 'f'))
2348 return (c - 'a') + 10;
2349 return 0;
2352 QString RTF2HTML::Parse(const char *rtf, const char *_encoding)
2354 encoding = _encoding;
2355 YY_BUFFER_STATE yy_current_buffer = rtf_scan_string(rtf);
2356 rtf_ptr = rtf;
2357 for (;;){
2358 int res = rtflex();
2359 if (!res) break;
2360 switch (res){
2361 case UP:{
2362 cur_level.flush();
2363 levels.push(cur_level);
2364 break;
2366 case DOWN:{
2367 if (!levels.empty()){
2368 cur_level.flush();
2369 cur_level.reset();
2370 cur_level = levels.top();
2371 levels.pop();
2373 break;
2375 case IMG:{
2376 cur_level.flush();
2377 const char ICQIMAGE[] = "icqimage";
2378 const char *smiles[] = { ":-)" , ":-O" , ":-|" , ":-/" , // 0-3
2379 ":-(" , ":-*" , ":-/" , ":'(" , // 4-7
2380 ";-)" , ":-@" , ":-$" , ":-X" , // 8-B
2381 ":-P" , "8-)" , "O:)" , ":-D" }; // C-F
2382 const char *p = rtftext + 3;
2383 if ((strlen(p) > strlen(ICQIMAGE)) && !memcmp(p, ICQIMAGE, strlen(ICQIMAGE))){
2384 unsigned n = 0;
2385 for (p += strlen(ICQIMAGE); *p; p++){
2386 if ((*p >= '0') && (*p <= '9')){
2387 n = n << 4;
2388 n += (*p - '0');
2389 continue;
2391 if ((*p >= 'A') && (*p <= 'F')){
2392 n = n << 4;
2393 n += (*p - 'A') + 10;
2394 continue;
2396 if ((*p >= 'a') && (*p <= 'f')){
2397 n = n << 4;
2398 n += (*p - 'a') + 10;
2399 continue;
2401 break;
2403 if (n < 16)
2404 PrintUnquoted(" %s ", smiles[n] );
2405 }else{
2406 // kDebug(14191) << "Unknown image " << rtftext;
2408 break;
2410 case SKIP:
2411 break;
2412 case SLASH:
2413 cur_level.setText(rtftext+1);
2414 break;
2415 case TXT:
2416 cur_level.setText(rtftext);
2417 break;
2418 case UNICODE_CHAR:{
2419 cur_level.flush();
2420 sParagraph += QChar((unsigned short)(atol(rtftext + 2)));
2421 break;
2423 case HEX:{
2424 char s[2];
2425 s[0] = (h2d(rtftext[2]) << 4) + h2d(rtftext[3]);
2426 s[1] = 0;
2427 cur_level.setText(s);
2428 break;
2430 case CMD:
2432 cur_level.flush();
2433 const char *cmd = rtftext + 1;
2434 unsigned n_cmd = 0;
2435 unsigned cmd_size = 0;
2436 int cmd_value = -1;
2437 const char *p;
2438 for (p = cmd; *p; p++, cmd_size++)
2439 if (((*p >= '0') && (*p <= '9')) || (*p == ' ')) break;
2440 if (*p && (*p != ' ')) cmd_value = atol(p);
2441 for (p = cmds; *p; p += strlen(p) + 1, n_cmd++){
2442 if (strlen(p) > cmd_size) continue;
2443 if (!memcmp(p, cmd, cmd_size)) break;
2445 cmd += strlen(p);
2446 switch (n_cmd){
2447 case FONTTBL: // fonttbl
2448 cur_level.setFontTbl();
2449 break;
2450 case COLORTBL:
2451 cur_level.setColors();
2452 break;
2453 case RED:
2454 cur_level.setRed(cmd_value);
2455 break;
2456 case GREEN:
2457 cur_level.setGreen(cmd_value);
2458 break;
2459 case BLUE:
2460 cur_level.setBlue(cmd_value);
2461 break;
2462 case CF:
2463 cur_level.setFontColor(cmd_value);
2464 break;
2465 case FS:
2466 cur_level.setFontSizeHalfPoints(cmd_value);
2467 break;
2468 case HIGHLIGHT:
2469 cur_level.setFontBgColor(cmd_value);
2470 break;
2471 case PARD:
2472 cur_level.clearParagraphFormatting();
2473 break;
2474 case PAR:
2475 cur_level.startParagraph();
2476 break;
2477 case I:
2478 cur_level.setItalic(cmd_value != 0);
2479 break;
2480 case B:
2481 cur_level.setBold(cmd_value != 0);
2482 break;
2483 case UL:
2484 cur_level.setUnderline(cmd_value != 0);
2485 break;
2486 case ULNONE:
2487 cur_level.setUnderline(false);
2488 break;
2489 case F:
2490 // RTF fonts are 0-based; our font index is 1-based.
2491 cur_level.setFont(cmd_value+1);
2492 break;
2493 case FCHARSET:
2494 cur_level.setEncoding(cmd_value);
2495 break;
2496 case FNAME:
2497 cur_level.setFontName();
2498 break;
2499 case LTRPAR:
2500 cur_level.setParagraphDirLTR();
2501 break;
2502 case RTLPAR:
2503 cur_level.setParagraphDirRTL();
2504 break;
2505 case LINE:
2506 cur_level.addLineBreak();
2508 break;
2512 rtf_delete_buffer(yy_current_buffer);
2513 yy_current_buffer = NULL;
2514 FlushParagraph();
2515 return s;
2519 bool ICQClient::parseRTF(const char *rtf, const char *encoding, QString &res)
2521 char _RTF[] = "{\\rtf";
2522 if ((strlen(rtf) > strlen(_RTF)) && !memcmp(rtf, _RTF, strlen(_RTF))){
2523 RTF2HTML p;
2524 res = p.Parse(rtf, encoding);
2525 return true;
2527 QTextCodec *codec = ICQClient::_getCodec(encoding);
2528 res = codec->toUnicode(rtf, strlen(rtf));
2529 return false;