source: trunk/mgpp/text/TextEl.cpp@ 3365

Last change on this file since 3365 was 3365, checked in by kjdon, 22 years ago

Initial revision

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 5.3 KB
Line 
1/**************************************************************************
2 *
3 * TextEl.cpp -- Data structures for parsed documents
4 * Copyright (C) 1999 Rodger McNab
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *
20 **************************************************************************/
21
22#include "TextEl.h"
23#include "ctype.h"
24
25#define REC_TERM '\002'
26#define PARA_TERM '\003'
27
28
29void TextEl::Clear () {
30 elType = TextE;
31 tagName.erase (tagName.begin(), tagName.end());
32 text.erase (text.begin(), text.end());
33}
34
35
36static bool ReadTextTag (FileBuf &buf, TextEl &el) {
37 // we must have some sort of tag
38 unsigned char c;
39 if (!buf.Peek(c)) return false;
40
41 // get the '<'
42 if (c != '<') return false;
43 el.text.push_back (c);
44 if (!buf.Next() || !buf.Peek (c)) return false;
45
46 // see if we have a '/'
47 if (c == '/') {
48 // we have a closing tag
49 el.text.push_back (c);
50 if (!buf.Next() || !buf.Peek (c)) return false;
51 el.elType = CloseTagE;
52 } else {
53 // we have an opening tag
54 el.elType = OpenTagE;
55 }
56
57 // get the tag name
58 while (isalnum(c)) {
59 el.text.push_back (c);
60 el.tagName.push_back (c);
61 if (!buf.Next() || !buf.Peek (c)) return false;
62 }
63
64 // get everything up to the closing '>'
65 while (c != '>') {
66 el.text.push_back (c);
67 if (!buf.Next() || !buf.Peek (c)) return false;
68 }
69
70 // get the closing '>'
71 el.text.push_back (c);
72 buf.Next();
73
74 // if there is no tag name then make this a text element
75 if (el.tagName.empty()) el.elType = TextE;
76
77 return true;
78}
79
80static void ToggleParaTag (TextEl &el, bool &compatInPara) {
81 SetCStr (el.tagName, "Paragraph");
82 el.text.erase (el.text.begin(), el.text.end());
83 if (compatInPara) {
84 el.elType = CloseTagE;
85 el.text.push_back (PARA_TERM);
86 } else el.elType = OpenTagE;
87 compatInPara = !compatInPara;
88}
89
90static void SetRecTag (TextEl &el, TextElType elType) {
91 el.elType = elType;
92 SetCStr (el.tagName, "Document");
93 el.text.erase (el.text.begin(), el.text.end());
94 if (elType == CloseTagE)
95 el.text.push_back (REC_TERM);
96}
97
98
99bool ReadTextEl (FileBuf &buf, TextEl &el,
100 bool compatMode, bool &compatInPara) {
101 el.Clear();
102
103 unsigned char c;
104 if (!buf.Peek (c)) return false;
105
106 if (compatMode) {
107 if (c == PARA_TERM) {
108 ToggleParaTag (el, compatInPara);
109 if (!compatInPara) buf.Next();
110 return true;
111 }
112 if (c == REC_TERM) {
113 if (compatInPara) {
114 // need to close this paragraph
115 ToggleParaTag (el, compatInPara);
116 return true;
117 }
118 // can close this document
119 buf.Next();
120 SetRecTag (el, CloseTagE);
121 return true;
122 }
123 if (!compatInPara) {
124 // need to open a paragraph
125 ToggleParaTag (el, compatInPara);
126 return true;
127 }
128 }
129
130 // see if we have some sort of tag
131 if (c == '<') return ReadTextTag (buf, el);
132
133 // read in a text element
134 el.elType = TextE;
135 while (c != '<' && !(compatMode && (c == PARA_TERM || c == REC_TERM))) {
136 el.text.push_back (c);
137 if (!buf.Next() || !buf.Peek (c)) break;
138 }
139
140 return true;
141}
142
143static void AddTextEl (TextElArray &doc, unsigned long &docLen,
144 const TextEl &el) {
145 doc.push_back (el);
146 docLen += el.text.size();
147
148// cout << "elType: " << el.elType << "\n";
149// cout << "tagName: " << el.tagName << "\n";
150// cout << "text: \"" << el.text << "\"\n\n";
151}
152
153
154bool ReadDoc (FileBuf &buf, const UCArray &docTag,
155 TextElArray &doc, unsigned long &docLen,
156 bool compatMode) {
157 bool compatInPara = false;
158 bool foundDocEl = false;
159 TextEl el;
160
161 doc.erase (doc.begin(), doc.end());
162 docLen = 0;
163
164 if (compatMode) {
165 // add <Document><Paragraph>
166 SetRecTag (el, OpenTagE);
167 AddTextEl (doc, docLen, el);
168 ToggleParaTag (el, compatInPara);
169 AddTextEl (doc, docLen, el);
170
171 } else {
172 // look for an opening docTag
173 do {
174 if (!ReadTextEl (buf, el, compatMode, compatInPara)) return false;
175 } while (el.elType != OpenTagE || el.tagName != docTag);
176
177 AddTextEl (doc, docLen, el);
178 }
179
180
181 // get all elements until the closing docTag
182 while (ReadTextEl (buf, el, compatMode, compatInPara)) {
183 foundDocEl = true;
184 AddTextEl (doc, docLen, el);
185 if (el.elType == CloseTagE && el.tagName == docTag)
186 return true;
187 }
188
189
190 if (compatMode) {
191 if (!foundDocEl) { // end of text
192 doc.erase (doc.begin(), doc.end());
193 return false;
194 }
195
196 // if we got here then the eof was encountered before
197 // the closing document tag
198 if (compatInPara) {
199 // need to close this paragraph
200 ToggleParaTag (el, compatInPara);
201 AddTextEl (doc, docLen, el);
202 }
203 // close this document
204 SetRecTag (el, CloseTagE);
205 AddTextEl (doc, docLen, el);
206 }
207
208 return true;
209}
210
211
Note: See TracBrowser for help on using the repository browser.