1 /* rtfGrammer.y
2 
3    Copyright (C) 1999 Free Software Foundation, Inc.
4 
5    Author:  Stefan B�hringer (stefan.boehringer@uni-bochum.de)
6    Date: Dec 1999
7 
8    This file is part of the GNUstep GUI Library.
9 
10    This library is free software; you can redistribute it and/or
11    modify it under the terms of the GNU Lesser General Public
12    License as published by the Free Software Foundation; either
13    version 2 of the License, or (at your option) any later version.
14 
15    This library is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
18    Lesser General Public License for more details.
19 
20    You should have received a copy of the GNU Lesser General Public
21    License along with this library; see the file COPYING.LIB.
22    If not, see <http://www.gnu.org/licenses/> or write to the
23    Free Software Foundation, 51 Franklin Street, Fifth Floor,
24    Boston, MA 02110-1301, USA.
25 */
26 
27 /*
28   if processed using -p GSRTFP (as recommended) it will introduce the following global symbols:
29   'GSRTFPparse', `GSRTFPlex', `GSRTFPerror', `GSRTFPnerrs', `GSRTFPlval',
30   `GSRTFPchar', `GSRTFPdebug
31 */
32 
33 /*	we request for a reentrant parser	*/
34 %define api.pure
35 
36 %{
37 
38 /*
39   The overall plan is to make this grammer universal in usage.
40   Intrested buddies can implement plain C functions to consume what
41   the grammer is producing. this way the rtf-grammer-tree can be
42   converted to what is needed: GNUstep attributed strings, tex files,
43   ...
44 
45   The plan is laid out by defining a set of C functions which cover
46   all what is needed to mangle rtf information (it is NeXT centric
47   however and may even lack some features).  Be aware that some
48   functions are called at specific times when some information may or
49   may not be available. The first argument of all functions is a
50   context, which is asked to be maintained by the consumer at
51   whichever purpose seems appropriate.  This context must be passed to
52   the parser by issuing 'value = GSRTFparse(ctxt, lctxt);' in the
53   first place.
54 */
55 
56 #import <AppKit/AppKit.h>
57 #include <stdlib.h>
58 #include <string.h>
59 #include "rtfScanner.h"
60 
61 /*	this context is passed to the interface functions	*/
62 typedef void	*GSRTFctxt;
63 /*#undef YYLSP_NEEDED*/
64 #define CTXT            ctxt
65 
66 #define	YYERROR_VERBOSE
67 #define YYDEBUG 1
68 
69 #include "RTFConsumerFunctions.h"
70 /*int GSRTFlex (YYSTYPE *lvalp, RTFscannerCtxt *lctxt); */
71 int GSRTFlex(void *lvalp, void *lctxt);
72 
73 /* */
74 int fieldStart = 0;
75 
76 %}
77 
78 %parse-param {void *ctxt}
79 %parse-param {void *lctxt}
80 %lex-param {void *lctxt}
81 
82 %union {
83 	int		number;
84 	const char	*text;
85 	RTFcmd		cmd;
86 }
87 
88 /*	<!><p> RTFtext values have to be freed	*/
89 %token <text> RTFtext
90 %token RTFstart
91 %token RTFansi
92 %token RTFmac
93 %token RTFpc
94 %token RTFpca
95 %token RTFignore
96 %token RTFinfo
97 %token RTFstylesheet
98 %token RTFfootnote
99 %token RTFheader
100 %token RTFfooter
101 %token RTFpict
102 %token RTFplain
103 %token RTFparagraph
104 %token RTFdefaultParagraph
105 %token RTFrow
106 %token RTFcell
107 %token RTFtabulator
108 %token RTFemdash
109 %token RTFendash
110 %token RTFemspace
111 %token RTFenspace
112 %token RTFbullet
113 %token RTFfield
114 %token RTFfldinst
115 %token RTFfldalt
116 %token RTFfldrslt
117 %token RTFflddirty
118 %token RTFfldedit
119 %token RTFfldlock
120 %token RTFfldpriv
121 %token RTFfttruetype
122 %token RTFlquote
123 %token RTFrquote
124 %token RTFldblquote
125 %token RTFrdblquote
126 %token <cmd> RTFred
127 %token <cmd> RTFgreen
128 %token <cmd> RTFblue
129 %token <cmd> RTFcolorbg
130 %token <cmd> RTFcolorfg
131 %token <cmd> RTFunderlinecolor
132 %token <cmd> RTFcolortable
133 %token <cmd> RTFfont
134 %token <cmd> RTFfontSize
135 %token <cmd> RTFNeXTGraphic
136 %token <cmd> RTFNeXTGraphicWidth
137 %token <cmd> RTFNeXTGraphicHeight
138 %token <cmd> RTFNeXTHelpLink
139 %token <cmd> RTFNeXTHelpMarker
140 %token <cmd> RTFNeXTfilename
141 %token <cmd> RTFNeXTmarkername
142 %token <cmd> RTFNeXTlinkFilename
143 %token <cmd> RTFNeXTlinkMarkername
144 %token <cmd> RTFpaperWidth
145 %token <cmd> RTFpaperHeight
146 %token <cmd> RTFmarginLeft
147 %token <cmd> RTFmarginRight
148 %token <cmd> RTFmarginTop
149 %token <cmd> RTFmarginButtom
150 %token <cmd> RTFfirstLineIndent
151 %token <cmd> RTFleftIndent
152 %token <cmd> RTFrightIndent
153 %token <cmd> RTFalignCenter
154 %token <cmd> RTFalignJustified
155 %token <cmd> RTFalignLeft
156 %token <cmd> RTFalignRight
157 %token <cmd> RTFlineSpace
158 %token <cmd> RTFspaceAbove
159 %token <cmd> RTFstyle
160 %token <cmd> RTFbold
161 %token <cmd> RTFitalic
162 %token <cmd> RTFunderline
163 %token <cmd> RTFunderlineDot
164 %token <cmd> RTFunderlineDash
165 %token <cmd> RTFunderlineDashDot
166 %token <cmd> RTFunderlineDashDotDot
167 %token <cmd> RTFunderlineDouble
168 %token <cmd> RTFunderlineStop
169 %token <cmd> RTFunderlineThick
170 %token <cmd> RTFunderlineThickDot
171 %token <cmd> RTFunderlineThickDash
172 %token <cmd> RTFunderlineThickDashDot
173 %token <cmd> RTFunderlineThickDashDotDot
174 %token <cmd> RTFunderlineWord
175 %token <cmd> RTFstrikethrough
176 %token <cmd> RTFstrikethroughDouble
177 %token <cmd> RTFunichar
178 %token <cmd> RTFsubscript
179 %token <cmd> RTFsuperscript
180 %token <cmd> RTFtabstop
181 %token <cmd> RTFfcharset
182 %token <cmd> RTFfprq
183 %token <cmd> RTFcpg
184 %token <cmd> RTFansicpg
185 %token <cmd> RTFOtherStatement
186 %token RTFfontListStart
187 
188 //	<!> we assume token numbers to be sequential
189 //	\fnil | \froman | \fswiss | \fmodern | \fscript | \fdecor | \ftech
190 //	look at rtfScanner.h for enum definition
191 %token	RTFfamilyNil
192 %token	RTFfamilyRoman
193 %token	RTFfamilySwiss
194 %token	RTFfamilyModern
195 %token	RTFfamilyScript
196 %token	RTFfamilyDecor
197 %token	RTFfamilyTech
198 %token	RTFfamilyBiDi
199 
200 %type	<number> rtfFontFamily rtfCharset rtfFontStatement
201 %type	<text> rtfFieldinst
202 
203 /*	let's go	*/
204 
205 %%
206 
207 rtfFile:	'{' { GSRTFstart(CTXT); } RTFstart rtfIngredients { GSRTFstop(CTXT); } '}'
208 		;
209 
210 rtfCharset: RTFansi { GSRTFencoding(CTXT, 1); }
211 		|	RTFmac { GSRTFencoding(CTXT, 2); }
212 		|	RTFpc  { GSRTFencoding(CTXT, $$ = 3); }
213 		|	RTFpca { GSRTFencoding(CTXT, 4); }
214 		|	rtfCharset RTFansicpg { GSRTFencoding(CTXT, $2.parameter); }
215 		;
216 
217 rtfIngredients:	/*	empty	*/
218 		|	rtfIngredients rtfCharset
219 		|	rtfIngredients rtfFontList
220 		|	rtfIngredients rtfColorDef
221 		|	rtfIngredients rtfStatement
222 		|	rtfIngredients RTFtext		{ GSRTFmangleText(CTXT, $2); free((void *)$2); }
223 		|	rtfIngredients rtfBlock
224 		|	rtfIngredients error
225 		;
226 
227 rtfBlock:	'{' { GSRTFopenBlock(CTXT, NO); } rtfIngredients rtfNeXTstuff '}' { GSRTFcloseBlock(CTXT, NO); } /* may be empty */
228 		|	'{' { GSRTFopenBlock(CTXT, YES); } RTFignore rtfIngredients '}' { GSRTFcloseBlock(CTXT, YES); }
229 		|	'{' { GSRTFopenBlock(CTXT, YES); } RTFinfo rtfIngredients '}' { GSRTFcloseBlock(CTXT, YES); }
230 		|	'{' { GSRTFopenBlock(CTXT, YES); } RTFstylesheet rtfIngredients '}' { GSRTFcloseBlock(CTXT, YES); }
231 		|	'{' { GSRTFopenBlock(CTXT, YES); } RTFfootnote rtfIngredients '}' { GSRTFcloseBlock(CTXT, YES); }
232 		|	'{' { GSRTFopenBlock(CTXT, YES); } RTFheader rtfIngredients '}' { GSRTFcloseBlock(CTXT, YES); }
233 		|	'{' { GSRTFopenBlock(CTXT, YES); } RTFfooter rtfIngredients '}' { GSRTFcloseBlock(CTXT, YES); }
234 		|	'{' { GSRTFopenBlock(CTXT, YES); } RTFpict rtfIngredients '}' { GSRTFcloseBlock(CTXT, YES); }
235 		|	'{' { GSRTFopenBlock(CTXT, NO); } RTFfield rtfField '}' { GSRTFcloseBlock(CTXT, NO); }
236 		|	'{' error '}'
237 		;
238 
239 
240 rtfField: { fieldStart = GSRTFgetPosition(CTXT);} rtfFieldMod rtfFieldinst rtfFieldrslt { GSRTFaddField(CTXT, fieldStart, $3); free((void *)$3); }
241 		|	error
242 		;
243 
244 rtfFieldMod:	/*	empty	*/
245 		|	rtfFieldMod RTFflddirty
246 		|	rtfFieldMod RTFfldedit
247 		|	rtfFieldMod RTFfldlock
248 		|	rtfFieldMod RTFfldpriv
249 		;
250 
251 rtfIgnore:  	/*	empty	*/
252 		| RTFignore
253 		;
254 
255 rtfFieldinst: '{' rtfIgnore RTFfldinst RTFtext rtfFieldalt '}' { $$ = $4;}
256 		| '{' rtfIgnore RTFfldinst '{' { GSRTFopenBlock(CTXT, YES); } rtfStatementList RTFtext rtfFieldalt '}' { GSRTFcloseBlock(CTXT, YES); } '}' { $$ = $7;}
257 		| '{' error '}' { $$ = NULL;}
258 		;
259 
260 rtfFieldalt:  	/*	empty	*/
261 		| RTFfldalt
262 		;
263 
264 rtfFieldrslt: '{' rtfIgnore RTFfldrslt rtfIngredients '}'
265 		| '{' error '}'
266 		;
267 
268 rtfStatementList: 	/*	empty	*/
269 		| rtfStatementList rtfStatement
270 		| rtfStatementList rtfBlock
271 		;
272 
273 /*
274 	RTF statements start with a '\', have a alpha name and a number argument
275 */
276 
277 rtfStatement: RTFfont				{ int font;
278 
279 						  if ($1.isEmpty)
280 						      font = 0;
281 						  else
282 						      font = $1.parameter;
283 						  GSRTFfontNumber(CTXT, font); }
284 		|	RTFfontSize		{ int size;
285 
286 						  if ($1.isEmpty)
287 						      size = 24;
288 						  else
289 						      size = $1.parameter;
290 						  GSRTFfontSize(CTXT, size); }
291 		|	RTFpaperWidth		{ int width;
292 
293 		                                  if ($1.isEmpty)
294 						      width = 12240;
295 						  else
296 						      width = $1.parameter;
297 						  GSRTFpaperWidth(CTXT, width);}
298 		|	RTFpaperHeight		{ int height;
299 
300 		                                  if ($1.isEmpty)
301 						      height = 15840;
302 						  else
303 						      height = $1.parameter;
304 						  GSRTFpaperHeight(CTXT, height);}
305 		|	RTFmarginLeft		{ int margin;
306 
307 		                                  if ($1.isEmpty)
308 						      margin = 1800;
309 						  else
310 						      margin = $1.parameter;
311 						  GSRTFmarginLeft(CTXT, margin);}
312 		|	RTFmarginRight		{ int margin;
313 
314 		                                  if ($1.isEmpty)
315 						      margin = 1800;
316 						  else
317 						      margin = $1.parameter;
318 						  GSRTFmarginRight(CTXT, margin); }
319 		|	RTFmarginTop		{ int margin;
320 
321 		                                  if ($1.isEmpty)
322 						      margin = 1440;
323 						  else
324 						      margin = $1.parameter;
325 						  GSRTFmarginTop(CTXT, margin); }
326 		|	RTFmarginButtom		{ int margin;
327 
328 		                                  if ($1.isEmpty)
329 						      margin = 1440;
330 						  else
331 						      margin = $1.parameter;
332 						  GSRTFmarginButtom(CTXT, margin); }
333 		|	RTFfirstLineIndent	{ int indent;
334 
335 		                                  if ($1.isEmpty)
336 						      indent = 0;
337 						  else
338 						      indent = $1.parameter;
339 						  GSRTFfirstLineIndent(CTXT, indent); }
340 		|	RTFleftIndent		{ int indent;
341 
342 		                                  if ($1.isEmpty)
343 						      indent = 0;
344 						  else
345 						      indent = $1.parameter;
346 						  GSRTFleftIndent(CTXT, indent);}
347 		|	RTFrightIndent		{ int indent;
348 
349 		                                  if ($1.isEmpty)
350 						      indent = 0;
351 						  else
352 						      indent = $1.parameter;
353 						  GSRTFrightIndent(CTXT, indent);}
354 		|	RTFtabstop		{ int location;
355 
356 		                                  if ($1.isEmpty)
357 						      location = 0;
358 						  else
359 						      location = $1.parameter;
360 						  GSRTFtabstop(CTXT, location);}
361 		|	RTFalignCenter		{ GSRTFalignCenter(CTXT); }
362 		|	RTFalignJustified	{ GSRTFalignJustified(CTXT); }
363 		|	RTFalignLeft		{ GSRTFalignLeft(CTXT); }
364 		|	RTFalignRight		{ GSRTFalignRight(CTXT); }
365 		|	RTFspaceAbove		{ int space;
366 
367 		                                  if ($1.isEmpty)
368 						      space = 0;
369 						  else
370 						      space = $1.parameter;
371 						  GSRTFspaceAbove(CTXT, space); }
372 		|	RTFlineSpace		{ GSRTFlineSpace(CTXT, $1.parameter); }
373 		|	RTFdefaultParagraph	{ GSRTFdefaultParagraph(CTXT); }
374 		|	RTFstyle		{ GSRTFstyle(CTXT, $1.parameter); }
375 		|	RTFcolorbg		{ int color;
376 
377 		                                  if ($1.isEmpty)
378 						      color = 0;
379 						  else
380 						      color = $1.parameter;
381 						  GSRTFcolorbg(CTXT, color); }
382 		|	RTFcolorfg		{ int color;
383 
384 		                                  if ($1.isEmpty)
385 						      color = 0;
386 						  else
387 						      color = $1.parameter;
388 						  GSRTFcolorfg(CTXT, color); }
389 		|	RTFunderlinecolor	{ int color;
390 
391 		                                  if ($1.isEmpty)
392 						      color = 0;
393 						  else
394 						      color = $1.parameter;
395 						  GSRTFunderlinecolor(CTXT, color); }
396 		|	RTFsubscript		{ int script;
397 
398 		                                  if ($1.isEmpty)
399 						      script = 6;
400 						  else
401 						      script = $1.parameter;
402 						  GSRTFsubscript(CTXT, script); }
403 		|	RTFsuperscript		{ int script;
404 
405 		                                  if ($1.isEmpty)
406 						      script = 6;
407 						  else
408 						      script = $1.parameter;
409 						  GSRTFsuperscript(CTXT, script); }
410 		|	RTFbold			{ BOOL on;
411 
412 		                                  if ($1.isEmpty || $1.parameter)
413 						      on = YES;
414 						  else
415 						      on = NO;
416 						  GSRTFbold(CTXT, on); }
417 		|	RTFitalic		{ BOOL on;
418 
419 		                                  if ($1.isEmpty || $1.parameter)
420 						      on = YES;
421 						  else
422 						      on = NO;
423 						  GSRTFitalic(CTXT, on); }
424 		|	RTFunderline		{ BOOL on;
425 
426 		                                  if ($1.isEmpty || $1.parameter)
427 						      on = YES;
428 						  else
429 						      on = NO;
430 						  GSRTFunderline(CTXT, on, NSUnderlineStyleSingle | NSUnderlinePatternSolid); }
431 		|	RTFunderlineDot		{ BOOL on;
432 
433 		                                  if ($1.isEmpty || $1.parameter)
434 						      on = YES;
435 						  else
436 						      on = NO;
437 						  GSRTFunderline(CTXT, on, NSUnderlineStyleSingle | NSUnderlinePatternDot); }
438 		|	RTFunderlineDash	{ BOOL on;
439 
440 		                                  if ($1.isEmpty || $1.parameter)
441 						      on = YES;
442 						  else
443 						      on = NO;
444 						  GSRTFunderline(CTXT, on, NSUnderlineStyleSingle | NSUnderlinePatternDash); }
445 		|	RTFunderlineDashDot	{ BOOL on;
446 
447 		                                  if ($1.isEmpty || $1.parameter)
448 						      on = YES;
449 						  else
450 						      on = NO;
451 						  GSRTFunderline(CTXT, on, NSUnderlineStyleSingle | NSUnderlinePatternDashDot); }
452 		|	RTFunderlineDashDotDot	{ BOOL on;
453 
454 		                                  if ($1.isEmpty || $1.parameter)
455 						      on = YES;
456 						  else
457 						      on = NO;
458 						  GSRTFunderline(CTXT, on, NSUnderlineStyleSingle | NSUnderlinePatternDashDotDot); }
459 		|	RTFunderlineDouble	{ BOOL on;
460 
461 		                                  if ($1.isEmpty || $1.parameter)
462 						      on = YES;
463 						  else
464 						      on = NO;
465 						  GSRTFunderline(CTXT, on, NSUnderlineStyleDouble | NSUnderlinePatternSolid); }
466 |	RTFunderlineStop	{ GSRTFunderline(CTXT, NO, NSUnderlineStyleNone); }
467 		|	RTFunderlineThick	{ BOOL on;
468 
469 		                                  if ($1.isEmpty || $1.parameter)
470 						      on = YES;
471 						  else
472 						      on = NO;
473 						  GSRTFunderline(CTXT, on, NSUnderlineStyleThick | NSUnderlinePatternSolid); }
474 		|	RTFunderlineThickDot	{ BOOL on;
475 
476 		                                  if ($1.isEmpty || $1.parameter)
477 						      on = YES;
478 						  else
479 						      on = NO;
480 						  GSRTFunderline(CTXT, on, NSUnderlineStyleThick | NSUnderlinePatternDot); }
481 		|	RTFunderlineThickDash	{ BOOL on;
482 
483 		                                  if ($1.isEmpty || $1.parameter)
484 						      on = YES;
485 						  else
486 						      on = NO;
487 						  GSRTFunderline(CTXT, on, NSUnderlineStyleThick | NSUnderlinePatternDash); }
488 		|	RTFunderlineThickDashDot	{ BOOL on;
489 
490 		                                  if ($1.isEmpty || $1.parameter)
491 						      on = YES;
492 						  else
493 						      on = NO;
494 						  GSRTFunderline(CTXT, on, NSUnderlineStyleThick | NSUnderlinePatternDashDot); }
495 		|	RTFunderlineThickDashDotDot { BOOL on;
496 
497 		                                  if ($1.isEmpty || $1.parameter)
498 						      on = YES;
499 						  else
500 						      on = NO;
501 						  GSRTFunderline(CTXT, on, NSUnderlineStyleThick | NSUnderlinePatternDashDotDot); }
502 		|	RTFunderlineWord	{ BOOL on;
503 
504 		                                  if ($1.isEmpty || $1.parameter)
505 						      on = YES;
506 						  else
507 						      on = NO;
508 						  GSRTFunderline(CTXT, on, NSUnderlineStyleSingle | NSUnderlinePatternSolid | NSUnderlineByWordMask); }
509 |	RTFstrikethrough	{   NSInteger style;
510    if ($1.isEmpty || $1.parameter)
511      style = NSUnderlineStyleSingle | NSUnderlinePatternSolid;
512    else
513      style = NSUnderlineStyleNone;
514    GSRTFstrikethrough(CTXT, style); }
515 |	RTFstrikethroughDouble	{ GSRTFstrikethrough(CTXT, NSUnderlineStyleDouble | NSUnderlinePatternSolid); }
516 		|	RTFunichar	        { GSRTFunicode(CTXT, $1.parameter); }
517                 |	RTFplain	        { GSRTFdefaultCharacterStyle(CTXT); }
518                 |	RTFparagraph	        { GSRTFparagraph(CTXT); }
519                 |	RTFrow   	        { GSRTFparagraph(CTXT); }
520 		|	RTFOtherStatement	{ GSRTFgenericRTFcommand(CTXT, $1);
521 		                                  free((void*)$1.name); }
522 		;
523 
524 rtfNeXTstuff: /* empty */
525 		|	rtfNeXTGraphic
526 		|	rtfNeXTHelpLink
527 		|	rtfNeXTHelpMarker
528 		;
529 
530 /*
531 	NeXTGraphic (images)
532 	This is a Apple/NeXT extension. The format of the command is
533 	  {{\NeXTGraphic attachment \widthN \heightN} string}
534 	and the string is ignored (on OS X it is always 0xAC).
535 	See the Section "RTF Files and Attributed Strings" in Apple's
536 	Attributed Strings Programming Guide.
537 */
538 
539 rtfNeXTGraphic: '{' RTFNeXTGraphic RTFtext RTFNeXTGraphicWidth RTFNeXTGraphicHeight '}' { GSRTFopenBlock(CTXT, YES); } rtfIngredients { GSRTFcloseBlock(CTXT, YES); }
540 		{
541 			GSRTFNeXTGraphic (CTXT, $3, $4.parameter, $5.parameter);
542 		};
543 
544 /*
545 	NeXTHelpLink
546 	This is a NeXT extension. The format of the command is
547 	  {{\NeXTHelpLinkN \markername markername; \linkFilename filename;
548 	    \linkMarkername markername;} string}
549 	and the string is ignored (it is always 0xAC on NeXT).
550 	Note that the {\NeXTHelpLink } group may itself be preceded by
551 	other commands.
552 */
553 
554 rtfNeXTHelpLink: '{' RTFNeXTHelpLink RTFNeXTmarkername RTFtext RTFNeXTlinkFilename RTFtext RTFNeXTlinkMarkername RTFtext '}' { GSRTFopenBlock(CTXT, YES); } rtfIngredients { GSRTFcloseBlock(CTXT, YES); }
555 		{
556 			GSRTFNeXTHelpLink (CTXT, $2.parameter, $4, $6, $8);
557 		};
558 
559 /*
560 	NeXTHelpMarker
561 	This is a NeXT extension. The format of the command is
562 	  {{\NeXTHelpMarkerN \markername markername;} string}
563 	and the string is ignored (it is always 0xAC on NeXT).
564 	Note that the {\NeXTHelpLink } group may itself be preceded by
565 	other commands.
566 */
567 
568 rtfNeXTHelpMarker: '{' RTFNeXTHelpMarker RTFNeXTmarkername RTFtext '}' { GSRTFopenBlock(CTXT, YES); } rtfIngredients { GSRTFcloseBlock(CTXT, YES); }
569 		{
570 			GSRTFNeXTHelpMarker (CTXT, $2.parameter, $4);
571 		};
572 
573 /*
574 	Font description
575 */
576 
577 rtfFontList: '{' RTFfontListStart rtfFonts '}'
578 		;
579 
580 rtfFonts:
581 		|	rtfFonts rtfFontStatement
582 		|	rtfFonts '{' rtfFontStatement '}'
583 		|	rtfFonts '{' rtfFontStatement rtfBlock RTFtext '}'
584                     { free((void *)$5);}
585 		;
586 
587 /* the first RTFfont tags the font with a number */
588 /* RTFtext introduces the fontName */
589 rtfFontStatement:	RTFfont rtfFontFamily rtfFontAttrs RTFtext	{ GSRTFregisterFont(CTXT, $4, $2, $1.parameter);
590                                                           free((void *)$4); }
591 /* fbidi should be a font family, but it seems to be used differently */
592 		|	RTFfont RTFfamilyBiDi rtfFontFamily rtfFontAttrs RTFtext	{ GSRTFregisterFont(CTXT, $5, $3, $1.parameter);
593                                                           free((void *)$5); }
594 /* Theme fonts */
595 		|	RTFOtherStatement RTFfont RTFfamilyBiDi rtfFontFamily rtfFontAttrs RTFtext	{ GSRTFregisterFont(CTXT, $6, $4, $2.parameter);
596                                                           free((void *)$6); }
597 		;
598 
599 rtfFontAttrs: /* empty */
600                 | rtfFontAttrs RTFfcharset
601                 | rtfFontAttrs RTFfprq
602                 | rtfFontAttrs RTFcpg
603                 | rtfFontAttrs RTFfttruetype
604                 | rtfFontAttrs rtfBlock
605                 ;
606 
607 
608 rtfFontFamily:
609 			RTFfamilyNil	{ $$ = RTFfamilyNil - RTFfamilyNil; }
610 		|	RTFfamilyRoman	{ $$ = RTFfamilyRoman - RTFfamilyNil; }
611 		|	RTFfamilySwiss	{ $$ = RTFfamilySwiss - RTFfamilyNil; }
612 		|	RTFfamilyModern	{ $$ = RTFfamilyModern - RTFfamilyNil; }
613 		|	RTFfamilyScript	{ $$ = RTFfamilyScript - RTFfamilyNil; }
614 		|	RTFfamilyDecor	{ $$ = RTFfamilyDecor - RTFfamilyNil; }
615 		|	RTFfamilyTech	{ $$ = RTFfamilyTech - RTFfamilyNil; }
616 		;
617 
618 
619 /*
620 	Colour definition
621 */
622 
623 rtfColorDef: '{' RTFcolortable rtfColors '}'
624 		;
625 
626 rtfColors: /* empty */
627  		|	rtfColors rtfColorStatement
628 		;
629 
630 /* We get the ';' as RTFText */
631 rtfColorStatement: RTFred RTFgreen RTFblue RTFtext
632                      {
633 		       GSRTFaddColor(CTXT, $1.parameter, $2.parameter, $3.parameter);
634 		       free((void *)$4);
635 		     }
636  		|	RTFtext
637                      {
638 		       GSRTFaddDefaultColor(CTXT);
639 		       free((void *)$1);
640 		     }
641 		;
642 
643 /*
644 	some cludgy trailer
645 dummyNonTerminal: '\\' { @1.first_line; }	/ * we introduce a @n to fix the lex attributes * /
646 		;
647 */
648 
649 %%
650 
651 /*	some C code here	*/
652 
653