~xiphos-devel/gtkhtml/gconf-less

« back to all changes in this revision

Viewing changes to gtkhtml/test.c

  • Committer: Dmitrijs Ledkovs
  • Date: 2009-12-28 20:48:41 UTC
  • Revision ID: dmitrij.ledkov@gmail.com-20091228204841-4wwdvn5ei46teugv
Initial gtkhtml from Matthew

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- mode: c; c-basic-offset: 8 -*- */
 
2
 
 
3
/*
 
4
    This file is part of the GuileRepl library
 
5
 
 
6
    Copyright 2001 Ariel Rios <ariel@linuxppc.org>
 
7
 
 
8
    This library is free software; you can redistribute it and/or
 
9
    modify it under the terms of the GNU Library General Public
 
10
    License as published by the Free Software Foundation; either
 
11
    version 2 of the License, or (at your option) any later version.
 
12
 
 
13
    This library is distributed in the hope that it will be useful,
 
14
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
16
    Library General Public License for more details.
 
17
 
 
18
    You should have received a copy of the GNU Library General Public License
 
19
    along with this library; see the file COPYING.LIB.  If not, write to
 
20
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 
21
    Boston, MA 02110-1301, USA.
 
22
 
 
23
*/
 
24
#include <sys/types.h>
 
25
#include <sys/stat.h>
 
26
#include <fcntl.h>
 
27
#include <stdio.h>
 
28
#include <stdlib.h>
 
29
#include <unistd.h>
 
30
#include <string.h>
 
31
 
 
32
#include <gtk/gtk.h>
 
33
#include <glib/gi18n.h>
 
34
 
 
35
#include "gtkhtml.h"
 
36
#include "gtkhtmldebug.h"
 
37
#include "gtkhtml-stream.h"
 
38
 
 
39
#include "htmlengine.h"
 
40
 
 
41
typedef struct _Example Example;
 
42
 
 
43
struct _Example {
 
44
        const gchar *filename;
 
45
        const gchar *title;
 
46
};
 
47
 
 
48
static GPtrArray *examples;
 
49
 
 
50
GtkWidget *html;
 
51
 
 
52
static const gchar *welcome =
 
53
"Czech (&#268;e&#353;tina) &#268;au, Ahoj, Dobr&#253; den<BR>"
 
54
"French (Français) Bonjour, Salut<BR>"
 
55
"Korean (한글)   안녕하세요, 안녕하십니까<BR>"
 
56
"Russian (Русский) Здравствуйте!<BR>"
 
57
"Chinese (Simplified) <span lang=\"zh-cn\">元气   开发</span><BR>"
 
58
"Chinese (Traditional) <span lang=\"zh-tw\">元氣  開發</span><BR>"
 
59
"Japanese <span lang=\"ja\">元気  開発<BR></FONT>";
 
60
 
 
61
static void
 
62
url_requested (GtkHTML *unused, const gchar *url, GtkHTMLStream *stream, gpointer data)
 
63
{
 
64
        gint fd;
 
65
        gchar *filename;
 
66
 
 
67
        filename = g_strconcat ("tests/", url, NULL);
 
68
        fd = open (filename, O_RDONLY);
 
69
 
 
70
        if (fd != -1) {
 
71
#define MY_BUF_SIZE 32768
 
72
                gchar *buf;
 
73
                gsize size;
 
74
 
 
75
                buf = alloca (MY_BUF_SIZE);
 
76
                while ((size = read (fd, buf, MY_BUF_SIZE)) > 0) {
 
77
                        gtk_html_stream_write (stream, buf, size);
 
78
                }
 
79
                gtk_html_stream_close (stream, size == -1 ? GTK_HTML_STREAM_ERROR : GTK_HTML_STREAM_OK);
 
80
                close (fd);
 
81
        } else
 
82
                gtk_html_stream_close (stream, GTK_HTML_STREAM_ERROR);
 
83
 
 
84
        g_free (filename);
 
85
}
 
86
 
 
87
static gchar *
 
88
encode_html (const gchar *txt)
 
89
{
 
90
        GString *str;
 
91
        gchar *rv;
 
92
 
 
93
        str = g_string_new (NULL);
 
94
 
 
95
        do {
 
96
                gunichar uc;
 
97
 
 
98
                uc = g_utf8_get_char (txt);
 
99
                if (uc > 160) {
 
100
                        g_string_append_printf (str, "&#%u;", uc);
 
101
                } else {
 
102
                        g_string_append_c (str, uc);
 
103
                }
 
104
        } while ((txt = g_utf8_next_char (txt)) && *txt);
 
105
 
 
106
        rv = str->str;
 
107
        g_string_free (str, FALSE);
 
108
 
 
109
        return rv;
 
110
}
 
111
 
 
112
static void
 
113
example_changed_cb (GtkComboBox *combo_box, gpointer data)
 
114
{
 
115
        gint i = gtk_combo_box_get_active (combo_box);
 
116
        Example *example = examples->pdata[i];
 
117
 
 
118
        if (example->filename) {
 
119
                GtkHTMLStream *stream;
 
120
 
 
121
                stream = gtk_html_begin (GTK_HTML (html));
 
122
                url_requested (GTK_HTML (html), example->filename, stream, NULL);
 
123
        } else {
 
124
                gtk_html_load_from_string (GTK_HTML (html), encode_html (welcome), -1);
 
125
        }
 
126
}
 
127
 
 
128
static void
 
129
quit_cb (GtkWidget *button)
 
130
{
 
131
        gtk_main_quit ();
 
132
}
 
133
 
 
134
static void
 
135
dump_cb (GtkWidget *widget, gpointer data)
 
136
{
 
137
        g_print ("Object Tree\n");
 
138
        g_print ("-----------\n");
 
139
 
 
140
        gtk_html_debug_dump_tree (GTK_HTML (html)->engine->clue, 0);
 
141
}
 
142
 
 
143
static void
 
144
dump_simple_cb (GtkWidget *widget, gpointer data)
 
145
{
 
146
        g_print ("Simple Object Tree\n");
 
147
        g_print ("-----------\n");
 
148
 
 
149
        gtk_html_debug_dump_tree_simple (GTK_HTML (html)->engine->clue, 0);
 
150
}
 
151
 
 
152
static void
 
153
draw_page_cb (GtkPrintOperation *operation, GtkPrintContext *context,
 
154
              gint page_nr, gpointer user_data)
 
155
{
 
156
        gtk_html_print_page (GTK_HTML (html), context);
 
157
}
 
158
 
 
159
static void
 
160
print_cb (GtkWidget *widget, gpointer data)
 
161
{
 
162
        GtkPrintOperation *operation;
 
163
 
 
164
        operation = gtk_print_operation_new ();
 
165
        gtk_print_operation_set_n_pages (operation, 1);
 
166
 
 
167
        g_signal_connect (
 
168
                operation, "draw-page",
 
169
                G_CALLBACK (draw_page_cb), NULL);
 
170
 
 
171
        gtk_print_operation_run (
 
172
                operation, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
 
173
                NULL, NULL);
 
174
 
 
175
        g_object_unref (operation);
 
176
}
 
177
 
 
178
/* We want to sort "a2" < "b1" < "B1" < "b2" < "b12". Vastly
 
179
 * overengineered
 
180
 */
 
181
static gint
 
182
compare_examples (gconstpointer a,
 
183
                  gconstpointer b)
 
184
{
 
185
        const Example *example_a = *(const Example *const *)a;
 
186
        const Example *example_b = *(const Example *const *)b;
 
187
        gchar *a_fold, *b_fold;
 
188
        const guchar *p, *q;
 
189
        gint result = 0;
 
190
 
 
191
        /* Special case "Welcome" to sort first */
 
192
        if (!example_a->filename)
 
193
                return -1;
 
194
        if (!example_b->filename)
 
195
                return 1;
 
196
 
 
197
        a_fold = g_utf8_casefold (example_a->title, -1);
 
198
        b_fold = g_utf8_casefold (example_b->title, -1);
 
199
        p = (const guchar *)a_fold;
 
200
        q = (const guchar *)b_fold;
 
201
 
 
202
        while (*p && *q) {
 
203
                gboolean p_digit = g_ascii_isdigit (*p);
 
204
                gboolean q_digit = g_ascii_isdigit (*q);
 
205
 
 
206
                if (p_digit && !q_digit) {
 
207
                        result = 1;
 
208
                        goto out;
 
209
                }
 
210
                else if (!p_digit && q_digit) {
 
211
                        result = -1;
 
212
                        goto out;
 
213
                }
 
214
 
 
215
                if (p_digit) {
 
216
                        gint num_a = atoi ((const gchar *) p);
 
217
                        gint num_b = atoi ((const gchar *) q);
 
218
 
 
219
                        if (num_a < num_b) {
 
220
                                result = -1;
 
221
                                goto out;
 
222
                        }
 
223
                        else if (num_a > num_b) {
 
224
                                result = 1;
 
225
                                goto out;
 
226
                        }
 
227
 
 
228
                        while (g_ascii_isdigit (*p))
 
229
                                p++;
 
230
                        while (g_ascii_isdigit (*q))
 
231
                                q++;
 
232
 
 
233
                } else {
 
234
                        gint p_len = 1, q_len = 1;
 
235
                        gchar *p_str, *q_str;
 
236
 
 
237
                        while (*(p + p_len) && !g_ascii_isdigit (*(p + p_len)))
 
238
                                p_len++;
 
239
                        while (*(q + q_len) && !g_ascii_isdigit (*(q + q_len)))
 
240
                                q_len++;
 
241
 
 
242
                        p_str = g_strndup ((gchar *) p, p_len);
 
243
                        q_str = g_strndup ((gchar *) q, q_len);
 
244
 
 
245
                        result = g_utf8_collate (p_str, q_str);
 
246
                        g_free (p_str);
 
247
                        g_free (q_str);
 
248
 
 
249
                        if (result != 0)
 
250
                                goto out;
 
251
 
 
252
                        p += p_len;
 
253
                        q += p_len;
 
254
                }
 
255
 
 
256
                p++;
 
257
                q++;
 
258
        }
 
259
 
 
260
        if (*p)
 
261
                result = 1;
 
262
        else if (*q)
 
263
                result = -1;
 
264
        else
 
265
                result = g_utf8_collate (example_a->title, example_b->title);
 
266
 
 
267
 out:
 
268
        g_free (a_fold);
 
269
        g_free (b_fold);
 
270
 
 
271
        return result;
 
272
}
 
273
 
 
274
static void
 
275
find_examples (void)
 
276
{
 
277
        GDir *dir;
 
278
        GError *error;
 
279
        Example *example;
 
280
 
 
281
        examples = g_ptr_array_new ();
 
282
 
 
283
        example = g_new (Example, 1);
 
284
        example->filename = NULL;
 
285
        example->title = "Welcome";
 
286
        g_ptr_array_add (examples, example);
 
287
 
 
288
        dir = g_dir_open ("tests", 0, &error);
 
289
        if (!dir) {
 
290
                g_printerr ("Cannot open tests directory: %s\n", error->message);
 
291
                return;
 
292
        }
 
293
 
 
294
        while (TRUE) {
 
295
                const gchar *name = g_dir_read_name (dir);
 
296
 
 
297
                if (!name)
 
298
                        break;
 
299
                if (!g_str_has_suffix (name, ".html"))
 
300
                        continue;
 
301
 
 
302
                example = g_new (Example, 1);
 
303
                example->filename = g_strdup (name);
 
304
                example->title = g_strndup (name, strlen (name) - 5);
 
305
 
 
306
                g_ptr_array_add (examples, example);
 
307
                qsort (examples->pdata, examples->len, sizeof (gpointer), compare_examples);
 
308
        }
 
309
 
 
310
        g_dir_close (dir);
 
311
}
 
312
 
 
313
gint
 
314
main (gint argc, gchar **argv)
 
315
{
 
316
        GtkWidget *window;
 
317
        GtkWidget *vbox;
 
318
        GtkWidget *hbox;
 
319
        GtkWidget *combo_box;
 
320
        GtkWidget *swindow;
 
321
        GtkWidget *action_button;
 
322
        gint i = 0;
 
323
 
 
324
        gtk_init (&argc, &argv);
 
325
 
 
326
        find_examples ();
 
327
 
 
328
        window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
 
329
        vbox = gtk_vbox_new (FALSE, 0);
 
330
        hbox = gtk_hbox_new (FALSE, 0);
 
331
        swindow = gtk_scrolled_window_new (NULL, NULL);
 
332
        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
 
333
        html = gtk_html_new_from_string (encode_html (welcome), -1);
 
334
        g_signal_connect (html, "url_requested", G_CALLBACK (url_requested), NULL);
 
335
 
 
336
        gtk_container_add (GTK_CONTAINER (window), vbox);
 
337
        gtk_container_add (GTK_CONTAINER (swindow), html);
 
338
        gtk_box_pack_start (GTK_BOX (vbox), swindow, TRUE, TRUE, 0);
 
339
        gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
 
340
 
 
341
        combo_box = gtk_combo_box_new_text ();
 
342
        for (i = 0; i < examples->len; i++) {
 
343
                Example *example = examples->pdata[i];
 
344
                gtk_combo_box_append_text (GTK_COMBO_BOX (combo_box), example->title);
 
345
        }
 
346
        gtk_combo_box_set_active (GTK_COMBO_BOX (combo_box), 0);
 
347
        g_signal_connect (combo_box, "changed", G_CALLBACK (example_changed_cb), NULL);
 
348
 
 
349
        gtk_box_pack_start (GTK_BOX (hbox), combo_box, FALSE, FALSE, 0);
 
350
 
 
351
        action_button = gtk_button_new_with_label ("Dump");
 
352
        gtk_box_pack_end (GTK_BOX (hbox), action_button, FALSE, FALSE, 0);
 
353
        g_signal_connect (action_button, "clicked", G_CALLBACK (dump_cb), NULL);
 
354
        action_button = gtk_button_new_with_label ("Dump simple");
 
355
        gtk_box_pack_end (GTK_BOX (hbox), action_button, FALSE, FALSE, 0);
 
356
        g_signal_connect (action_button, "clicked", G_CALLBACK (dump_simple_cb), NULL);
 
357
        action_button = gtk_button_new_with_label ("Print");
 
358
        gtk_box_pack_end (GTK_BOX (hbox), action_button, FALSE, FALSE, 0);
 
359
        g_signal_connect (action_button, "clicked", G_CALLBACK (print_cb), window);
 
360
        action_button = gtk_button_new_with_label ("Quit");
 
361
        gtk_box_pack_end (GTK_BOX (hbox), action_button, FALSE, FALSE, 0);
 
362
        g_signal_connect (action_button, "clicked", G_CALLBACK (quit_cb), NULL);
 
363
 
 
364
        gtk_window_set_title (GTK_WINDOW (window), _("GtkHTML Test"));
 
365
        gtk_window_set_default_size (GTK_WINDOW (window), 500, 500);
 
366
 
 
367
        gtk_widget_show_all (window);
 
368
 
 
369
        gtk_main ();
 
370
 
 
371
        return 0;
 
372
 
 
373
}