1 /************************************************************************/
2 /*									*/
3 /*  Read an RTF text file into a BufferDocument				*/
4 /*									*/
5 /************************************************************************/
6 
7 #   include	"docRtfConfig.h"
8 
9 #   include	<stdio.h>
10 #   include	<ctype.h>
11 
12 #   include	<appDebugon.h>
13 
14 #   include	"docRtfReaderImpl.h"
15 #   include	"docRtfReadWrite.h"
16 #   include	"docRtfTagEnum.h"
17 #   include	"docRtfFlags.h"
18 #   include	<docRecalculateFields.h>
19 #   include	<docTreeType.h>
20 #   include	<docTreeNode.h>
21 #   include	<docNotes.h>
22 #   include	<docDebug.h>
23 
24 /************************************************************************/
25 
26 const char DOC_RTF_LENIENT_MESSAGE[]= "Use lenientRtf setting";
27 
28 /************************************************************************/
29 /*									*/
30 /*  Groups (Most of them handeled at the document level).		*/
31 /*									*/
32 /************************************************************************/
33 
34 RtfControlWord	docRtfDocumentGroups[]=
35 {
36     RTF_DEST_XX( "tc",		DOCfkTC,	docRtfLookupEntry ),
37     RTF_DEST_XX( "tcn",		DOCfkTCN,	docRtfLookupEntry ),
38 
39     RTF_DEST_XX( "nonesttables", 1,		docRtfSkipGroup ),
40 
41     RTF_DEST_XX( "trowd",	DOClevROW,	docRtfReadRowProperties ),
42 
43     { (char *)0, 0, 0 }
44 };
45 
46 /************************************************************************/
47 /*									*/
48 /*  Read a document as a whole.						*/
49 /*									*/
50 /************************************************************************/
51 
docRtfReadDoc(const RtfControlWord * rcw,int arg,RtfReader * rrc)52 static int docRtfReadDoc(	const RtfControlWord *	rcw,
53 				int			arg,
54 				RtfReader *		rrc )
55     {
56     int		rval= 0;
57     int		changed= 0;
58 
59     rrc->rrcSelectionScope.ssTreeType= DOCinBODY;
60 
61     rval= docRtfReadGroup( rcw, 0, 0, rrc,
62 				docRtfDocumentGroups,
63 				docRtfTextParticule,
64 				docRtfFinishCurrentNode );
65     if  ( rval )
66 	{ SLDEB(rcw->rcwWord,rval);	}
67 
68     docRenumberSeqFields( &changed, rrc->rrcTree, rrc->rrDocument );
69 
70     return rval;
71     }
72 
73 /************************************************************************/
74 /*									*/
75 /*  Read a whole document.						*/
76 /*									*/
77 /*  As at least MS-Word 2000 crashes on lists without an override,	*/
78 /*  and on the other hand staroffice/openoffice creates them under	*/
79 /*  certain circumstances: Make an empty override for lists without	*/
80 /*  overrides.								*/
81 /*									*/
82 /************************************************************************/
83 
84 static RtfControlWord	docRtfOutsideGroups[]=
85     {
86 	RTF_DEST_XX( "rtf",	0,	docRtfReadDoc ),
87 
88 	{ (char *)0, 0, 0 }
89     };
90 
docRtfReadFile(SimpleInputStream * sis,unsigned int flags)91 BufferDocument * docRtfReadFile(	SimpleInputStream *		sis,
92 					unsigned int			flags )
93     {
94     BufferDocument *		rval= (BufferDocument *)0;
95     BufferDocument *		bd= (BufferDocument *)0;
96     RtfReader *			rr= (RtfReader *)0;
97 
98     int				res;
99     const RtfControlWord *	rcw;
100 
101     char			controlWord[TEDszRTFCONTROL+1];
102     int				gotArg;
103     int				arg= -1;
104     int				c;
105 
106     const DocumentField *	dfNote;
107     struct DocumentNote *	dn;
108     int				changed;
109 
110     bd= docNewDocument( (BufferDocument *)0 );
111     if  ( ! bd )
112 	{ XDEB(bd); goto ready;	}
113 
114     rr= docRtfOpenReader( sis, bd, flags );
115     if  ( ! rr )
116 	{ XDEB(rr); goto ready;	}
117 
118     rr->rrcTree= &(rr->rrDocument->bdBody);
119     rr->rrcNode= rr->rrcTree->dtRoot;
120     rr->rrcLevel= DOClevBODY;
121 
122     res= docRtfFindControl( rr, &c, controlWord, &gotArg, &arg );
123     if  ( res != RTFfiCTRLGROUP )
124 	{ goto ready; }
125 
126     rcw= docRtfFindWord( controlWord, docRtfOutsideGroups );
127     if  ( ! rcw )
128 	{ LDEB(1); goto ready; }
129     if  ( rcw->rcwType != RTCtypeDEST )
130 	{ SLDEB(rcw->rcwWord,rcw->rcwType); goto ready;	}
131 
132     res= docRtfApplyControlWord( rcw, gotArg, arg, rr );
133     if  ( res )
134 	{ LDEB(1); goto ready; }
135 
136     /*  Check against trailing garbage. Spaces are not allowed either, 	*/
137     /*  but we do not want to scare the user with invisible things.	*/
138 
139     if  ( ! ( rr->rrReadFlags & RTFflagLENIENT ) )
140 	{
141 	c= sioInGetByte( sis );
142 	while( c != EOF )
143 	    {
144 	    if  ( c != '\r' && c != '\n' && c != '\0' && c != ' ' )
145 		{
146 		const char * message= DOC_RTF_LENIENT_MESSAGE;
147 		LCSDEB(rr->rrCurrentLine,c,message); goto ready;
148 		}
149 
150 	    c= sioInGetByte( sis );
151 	    }
152 	}
153 
154     if  ( ! rr->rrcGotDocGeometry		&&
155 	  bd->bdBody.dtRoot->biChildCount > 0	)
156 	{
157 	bd->bdProperties.dpGeometry=
158 		    bd->bdBody.dtRoot->biChildren[0]->biSectDocumentGeometry;
159 	}
160 
161     docRenumberNotes( &changed, bd );
162 
163     dfNote= docGetFirstNoteOfDocument( &dn, bd, DOCinFOOTNOTE );
164     if  ( dfNote )
165 	{
166 	if  ( docCheckSeparatorItemForNoteType( bd, DOCinFOOTNOTE ) )
167 	    { LDEB(DOCinFTNSEP); goto ready; }
168 	}
169 
170     dfNote= docGetFirstNoteOfDocument( &dn, bd, DOCinENDNOTE );
171     if  ( dfNote )
172 	{
173 	if  ( docCheckSeparatorItemForNoteType( bd, DOCinENDNOTE ) )
174 	    { LDEB(DOCinAFTNSEP); goto ready; }
175 	}
176 
177     if  ( docMakeOverrideForEveryList( bd->bdProperties.dpListAdmin ) )
178 	{ LDEB(1); goto ready;	}
179 
180     if  ( docGetCharsUsed( bd ) )
181 	{ LDEB(1); goto ready;	}
182 
183     rval= bd; bd= (BufferDocument *)0; /* steal */
184 
185     /* LDEB(1); docListNode(0,rval->bdBody.dtRoot,0); */
186 
187   ready:
188 
189     if  ( rr )
190 	{ docRtfCloseReader( rr );	}
191 
192     if  ( bd )
193 	{ docFreeDocument( bd );	}
194 
195     return rval;
196     }
197 
198 /************************************************************************/
199 /*									*/
200 /*  Remember properties to be used subsequently.			*/
201 /*									*/
202 /*  References are to be replaced with feature specific routine		*/
203 /*  refrerences.							*/
204 /*									*/
205 /************************************************************************/
206 
docRtfRememberProperty(const RtfControlWord * rcw,int arg,RtfReader * rrc)207 int docRtfRememberProperty(	const RtfControlWord *	rcw,
208 				int			arg,
209 				RtfReader *		rrc )
210     {
211     RtfReadingState *	rrs= rrc->rrcState;
212 
213     switch( rcw->rcwID )
214 	{
215 	case RTFidUC:
216 	    if  ( rrc->rrcState )
217 		{ rrc->rrcState->rrsBytesPerUnicode= arg;	}
218 	    break;
219 				/****************************************/
220 				/*  Set/Unset Text Attributes.		*/
221 				/****************************************/
222 	case RTFidULNONE:
223 	    rrs->rrsTextAttribute.taTextIsUnderlined= 0;
224 	    break;
225 				/****************************************/
226 				/*  Set/Unset Text Attributes.		*/
227 				/*  In Paragraph Numbering.		*/
228 				/****************************************/
229 	case RTFidPNULNONE:
230 	    rrc->rrcParagraphNumber.pnTextAttribute.taTextIsUnderlined= 0;
231 	    break;
232 
233 				/****************************************/
234 				/*  Paragraph Numbering.		*/
235 				/****************************************/
236 	case RTFidPNHANG:
237 	    rrc->rrcParagraphNumber.pnUseHangingIndent= 1;
238 	    break;
239 				/****************************************/
240 				/*  Unknown				*/
241 				/****************************************/
242 	default:
243 	    /*SLDEB(rcw->rcwWord,rcw->rcwID);*/
244 	    break;
245 	}
246 
247     return 0;
248     }
249