]> git.lyx.org Git - lyx.git/blob - src/sgml.C
Make enter button work in GTK text dialog
[lyx.git] / src / sgml.C
1 /**
2  * \file sgml.C
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author José Matos
7  * \author John Levon
8  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 #include <config.h>
13
14 #include "sgml.h"
15
16 #include "buffer.h"
17 #include "bufferparams.h"
18 #include "counters.h"
19 #include "lyxtext.h"
20 #include "outputparams.h"
21 #include "paragraph.h"
22
23 #include "support/lstrings.h"
24 #include "support/std_ostream.h"
25 #include "support/convert.h"
26
27 #include <boost/tuple/tuple.hpp>
28
29 #include <map>
30 #include <sstream>
31
32 using lyx::support::subst;
33
34 using std::make_pair;
35 using std::map;
36 using std::ostream;
37 using std::ostringstream;
38 using std::pair;
39 using std::string;
40
41 namespace sgml {
42
43 pair<bool, string> escapeChar(char c)
44 {
45         string str;
46
47         switch (c) {
48         case ' ':
49                 return make_pair(true, string(" "));
50                 break;
51         case '\0': // Ignore :-)
52                 str.erase();
53                 break;
54         case '&':
55                 str = "&amp;";
56                 break;
57         case '<':
58                 str = "&lt;";
59                 break;
60         case '>':
61                 str = "&gt;";
62                 break;
63 #if 0
64         case '$':
65                 str = "&dollar;";
66                 break;
67         case '#':
68                 str = "&num;";
69                 break;
70         case '%':
71                 str = "&percnt;";
72                 break;
73         case '[':
74                 str = "&lsqb;";
75                 break;
76         case ']':
77                 str = "&rsqb;";
78                 break;
79         case '{':
80                 str = "&lcub;";
81                 break;
82         case '}':
83                 str = "&rcub;";
84                 break;
85         case '~':
86                 str = "&tilde;";
87                 break;
88         case '"':
89                 str = "&quot;";
90                 break;
91         case '\\':
92                 str = "&bsol;";
93                 break;
94 #endif
95         default:
96                 str = c;
97                 break;
98         }
99         return make_pair(false, str);
100 }
101
102
103 string escapeString(string const & raw)
104 {
105         ostringstream bin;
106
107         for(string::size_type i = 0; i < raw.size(); ++i) {
108                 bool ws;
109                 string str;
110                 boost::tie(ws, str) = sgml::escapeChar(raw[i]);
111                 bin << str;
112         }
113         return bin.str();
114 }
115
116
117 string const uniqueID(string const label)
118 {
119         static unsigned int seed = 1000;
120         return label + convert<string>(++seed);
121 }
122
123
124 string cleanID(Buffer const & buf, OutputParams const & runparams, std::string const & orig)
125 {
126         // The standard DocBook SGML declaration only allows letters,
127         // digits, '-' and '.' in a name.
128         // Since users might change that declaration one has to cater
129         // for additional allowed characters.
130         // This routine replaces illegal characters by '-' or '.'
131         // and adds a number for uniqueness.
132         // If you know what you are doing, you can set allowed==""
133         // to disable this mangling.
134         LyXTextClass const & tclass = buf.params().getLyXTextClass();
135         string const allowed = runparams.flavor == OutputParams::XML? ".-_:":tclass.options();
136
137         if (allowed.empty())
138                 return orig;
139
140         string::const_iterator it  = orig.begin();
141         string::const_iterator end = orig.end();
142
143         string content;
144
145         typedef map<string, string> MangledMap;
146         static MangledMap mangledNames;
147         static int mangleID = 1;
148
149         MangledMap::const_iterator const known = mangledNames.find(orig);
150         if (known != mangledNames.end())
151                 return (*known).second;
152
153         // make sure it starts with a letter
154         if (!isalpha(*it) && allowed.find(*it) >= allowed.size())
155                 content += "x";
156
157         bool mangle = false;
158         for (; it != end; ++it) {
159                 char c = *it;
160                 if (isalpha(c) || isdigit(c) || c == '-' || c == '.' || allowed.find(c) < allowed.size())
161                         content += c;
162                 else if (c == '_' || c == ' ') {
163                         mangle = true;
164                         content += "-";
165                 }
166                 else if (c == ':' || c == ',' || c == ';' || c == '!') {
167                         mangle = true;
168                         content += ".";
169                 }
170                 else {
171                         mangle = true;
172                 }
173         }
174         if (mangle) {
175                 content += "-" + convert<string>(mangleID++);
176         }
177         else if (isdigit(content[content.size() - 1])) {
178                 content += ".";
179         }
180
181         mangledNames[orig] = content;
182
183         return content;
184 }
185
186
187 void openTag(ostream & os, string const & name, string const & attribute)
188 {
189         // This should be fixed in layout files later.
190         string param = subst(attribute, "<", "\"");
191         param = subst(param, ">", "\"");
192
193         if (!name.empty() && name != "!-- --") {
194                 os << '<' << name;
195                 if (!param.empty())
196                         os << " " << param;
197                 os << '>';
198         }
199 }
200
201
202 void closeTag(ostream & os, string const & name)
203 {
204         if (!name.empty() && name != "!-- --")
205                 os << "</" << name << '>';
206 }
207
208
209 void openTag(Buffer const & buf, ostream & os, OutputParams const & runparams, Paragraph const & par)
210 {
211         LyXLayout_ptr const & style = par.layout();
212         string const & name = style->latexname();
213         string param = style->latexparam();
214         Counters & counters = buf.params().getLyXTextClass().counters();
215
216         string id = par.getID(buf, runparams);
217
218         string attribute;
219         if(!id.empty()) {
220                 if (param.find('#') != string::npos) {
221                         string::size_type pos = param.find("id=<");
222                         string::size_type end = param.find(">");
223                         if( pos != string::npos && end != string::npos)
224                                 param.erase(pos, end-pos + 1);
225                 }
226                 attribute = id + ' ' + param;
227         } else {
228                 if (param.find('#') != string::npos) {
229                         if(!style->counter.empty())
230                                 counters.step(style->counter);
231                         else
232                                 counters.step(style->latexname());
233                         int i = counters.value(name);
234                         attribute = subst(param, "#", convert<string>(i));
235                 } else {
236                         attribute = param;
237                 }
238         }
239         openTag(os, name, attribute);
240 }
241
242
243 void closeTag(ostream & os, Paragraph const & par)
244 {
245         LyXLayout_ptr const & style = par.layout();
246         closeTag(os, style->latexname());
247 }
248
249 } // namespace sgml