3 * Copyright (C) 2008-2009 Florian Brosch, Didier Villevalois
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 * Didier 'Ptitjes Villevalois <ptitjes@free.fr>
25 * Writes markups and text to a file.
27 public class Valadoc
.MarkupWriter
{
28 protected WriteFunc write
;
31 protected long current_column
= 0;
32 protected bool last_was_tag
;
33 private bool wrap
= true;
35 public static string escape (string txt
) {
36 StringBuilder builder
= new
StringBuilder ();
37 unowned
string start
= txt
;
41 for (pos
= txt
; (c
= pos
.get_char ()) != '\0'; pos
= pos
.next_char ()) {
44 builder
.append_len (start
, (ssize_t
) ((char*) pos
- (char*) start
));
45 builder
.append (""");
46 start
= pos
.next_char ();
50 builder
.append_len (start
, (ssize_t
) ((char*) pos
- (char*) start
));
51 builder
.append ("<");
52 start
= pos
.next_char ();
56 builder
.append_len (start
, (ssize_t
) ((char*) pos
- (char*) start
));
57 builder
.append (">");
58 start
= pos
.next_char ();
62 builder
.append_len (start
, (ssize_t
) ((char*) pos
- (char*) start
));
63 builder
.append ("&");
64 start
= pos
.next_char ();
68 builder
.append_len (start
, (ssize_t
) ((char*) pos
- (char*) start
));
69 builder
.append ("'");
70 start
= pos
.next_char ();
78 builder
.append_len (start
, (ssize_t
) ((char*) pos
- (char*) start
));
79 return (owned
) builder
.str
;
84 * Writes text to a desination like a {@link GLib.StringBuilder} or a {@link GLib.FileStream}
86 public delegate
void WriteFunc (string text
);
88 private const int MAX_COLUMN
= 150;
91 * Initializes a new instance of the MarkupWriter
93 * @param write stream a WriteFunc
94 * @param xml_declaration specifies whether this file starts with an xml-declaration
96 public MarkupWriter (owned WriteFunc write
, bool xml_declaration
= true) {
97 this
.write
= (owned
) write
;
98 if (xml_declaration
) {
99 do_write ("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
106 * Writes an start tag of a markup element to the file
108 * @param name the name of the markup
109 * @param attributes a list of name/value pairs
112 public unowned MarkupWriter
start_tag (string name
, string[]? attributes
=null) {
116 if (attributes
.length
% 2 != 0) {
117 attributes
.resize (attributes
.length
+1);
118 attributes
[attributes
.length
-1] = "";
121 var content
= new
StringBuilder ("<");
122 content
.append (name
);
123 for (int i
= 0; i
< attributes
.length
; i
=i
+2) {
124 if (attributes
[i
+1] != null) {
125 content
.append_printf (" %s=\"%s\"", attributes
[i
], attributes
[i
+1]);
128 content
.append (">");
130 do_write (content
.str
);
136 * Writes a simple tag (<name />) to the file
138 * @param name the name of the markup
139 * @param attributes a list of name/value pairs
142 public unowned MarkupWriter
simple_tag (string name
, string[]? attributes
=null) {
146 if (attributes
.length
% 2 != 0) {
147 attributes
.resize (attributes
.length
+1);
148 attributes
[attributes
.length
-1] = "";
151 var content
= new
StringBuilder ("<");
152 content
.append (name
);
153 for (int i
= 0; i
< attributes
.length
; i
=i
+2) {
154 if (attributes
[i
+1] != null) {
155 content
.append_printf (" %s=\"%s\"", attributes
[i
], attributes
[i
+1]);
158 content
.append ("/>");
160 do_write (content
.str
);
167 * Writes an end tag of a markup element to the file
169 * @param name the name of the markup
172 public unowned MarkupWriter
end_tag (string name
) {
173 check_column (name
, true);
174 do_write ("</%s>".printf (name
));
181 * Writes the specified string to the output stream
186 public unowned MarkupWriter
text (string text
) {
187 if (wrap
&& text
.length
+ current_column
> MAX_COLUMN
) {
189 while (wrote
< text
.length
) {
191 for (long i
= wrote
+ 1; i
< text
.length
; i
++) {
192 if (text
[i
] == ' ') {
193 if (i
- wrote
+ current_column
> MAX_COLUMN
) {
199 if (text
.length
- wrote
+ current_column
<= MAX_COLUMN
) {
200 do_write (text
.substring (wrote
));
201 wrote
= text
.length
+ 1;
202 } else if (space_pos
== -1) {
205 do_write (text
.substring (wrote
, space_pos
- wrote
));
206 wrote
= space_pos
+ 1;
208 if (wrote
< text
.length
) {
216 last_was_tag
= false;
221 * Writes the specified string to the output stream
226 public unowned MarkupWriter
raw_text (string text
) {
228 last_was_tag
= false;
232 public void set_wrap (bool wrap
) {
236 private void break_line () {
238 write (string.nfill (indent
* 2, ' '));
239 current_column
= indent
* 2;
242 protected void do_write (string text
) {
243 if (wrap
&& current_column
+ text
.length
> MAX_COLUMN
) {
247 current_column
+= text
.length
;
250 private void check_column (string name
, bool end_tag
= false) {
253 } else if (!end_tag
&& inline_element (name
) /*&& !last_was_tag*/) {
255 } else if (end_tag
&& content_inline_element (name
)) {
257 } else if (end_tag
&& !last_was_tag
) {
263 protected virtual bool inline_element (string name
) {
267 protected virtual bool content_inline_element (string name
) {