summaryrefslogtreecommitdiff
path: root/examples/viewer-win32.c
diff options
context:
space:
mode:
authorTor Lillqvist <tml@iki.fi>2000-07-15 01:06:08 +0000
committerTor Lillqvist <tml@src.gnome.org>2000-07-15 01:06:08 +0000
commit932fe1e3da39b3d8febfca65f6ca5312f0397ed1 (patch)
treed5583d408b5af1a4ed899a78937fc76ed46c442d /examples/viewer-win32.c
parentd4fb416c99d0066aafed26306a421a7bd22289e3 (diff)
downloadpango-932fe1e3da39b3d8febfca65f6ca5312f0397ed1.tar.gz
pango/pangowin32.h pango/pangowin32-private.h pango/pangowin32-fontcache.c
2000-07-15 Tor Lillqvist <tml@iki.fi> * pango/pangowin32.h * pango/pangowin32-private.h * pango/pangowin32-fontcache.c * pango/pangowin32-fontmap.c * modules/basic/basic-win32.c * examples/viewer-win32.c * examples/pangowin32.aliases: New files. Start of a Win32 implementation. Does not work yet. * configure.in: Chek for dirent.h and unistd.h. * pango/pango-utils.h * pango/pango-utils.c (pango_get_sysconf_subdirectory, pango_get_lib_subdirectory): New functions, for better portability, to enable installation-time choice of directory (on Windows) instead of compile-time. Use these instead of SYSCONFDIR "/pango" and LIBDIR "/pango". (pango_split_file_list): Fix comment, the function splits on searchpath separators, not commas. Use G_SEARCHPATH_SEPARATOR_S for portability. Don't try to expand '~' as home directory on Windows. (read_config): Use pango_get_sysconf_subdirectory(). * pango/modules.c (read_modules): Use pango_get_sysconf_subdirectory(). Don't crash if a module file cannot be opened. * pango/querymodules.c: Include config.h Conditionalize inclusion of dirent.h and unistd.h. Use platform-specific shared library extension. Use pango_get_lib_subdirectory().
Diffstat (limited to 'examples/viewer-win32.c')
-rw-r--r--examples/viewer-win32.c742
1 files changed, 742 insertions, 0 deletions
diff --git a/examples/viewer-win32.c b/examples/viewer-win32.c
new file mode 100644
index 00000000..9304b7d2
--- /dev/null
+++ b/examples/viewer-win32.c
@@ -0,0 +1,742 @@
+#define PING() g_print ("%s:%d\n", __PRETTY_FUNCTION__, __LINE__)
+/* Pango
+ * viewer-win32.c: Example program to view a UTF-8 encoding file
+ * using Pango to render result.
+ *
+ * Copyright (C) 1999 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <gtk/gtk.h>
+#include <gdk/win32/gdkwin32.h>
+
+#include <pango/pango.h>
+#include <pango/pangowin32.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#define BUFSIZE 1024
+
+typedef struct _Paragraph Paragraph;
+
+/* Structure representing a paragraph
+ */
+struct _Paragraph {
+ char *text;
+ int length;
+ int height; /* Height, in pixels */
+ PangoLayout *layout;
+};
+
+GList *paragraphs;
+
+static PangoFontDescription font_description;
+static Paragraph *highlight_para;
+static int highlight_offset;
+
+GtkWidget *styles_combo;
+
+static GtkWidget *message_label;
+GtkWidget *layout;
+
+PangoContext *context;
+
+static void fill_styles_combo (GtkWidget *combo);
+
+/* Read an entire file into a string
+ */
+static char *
+read_file(char *name)
+{
+ GString *inbuf;
+ FILE *file;
+ char *text;
+ char buffer[BUFSIZE];
+
+ PING();
+ file = fopen (name, "r");
+ if (!file)
+ {
+ fprintf (stderr, "%s: Cannot open %s\n", g_get_prgname ());
+ return NULL;
+ }
+
+ inbuf = g_string_new (NULL);
+ while (1)
+ {
+ char *bp = fgets (buffer, BUFSIZE-1, file);
+ if (ferror (file))
+ {
+ fprintf(stderr, "%s: Error reading %s\n", g_get_prgname ());
+ g_string_free (inbuf, TRUE);
+ return NULL;
+ }
+ else if (bp == NULL)
+ break;
+
+ g_string_append (inbuf, buffer);
+ }
+
+ fclose (file);
+
+ text = inbuf->str;
+ g_string_free (inbuf, FALSE);
+
+ return text;
+}
+
+/* Take a UTF8 string and break it into paragraphs on \n characters
+ */
+static GList *
+split_paragraphs (char *text)
+{
+ char *p = text;
+ char *next;
+ gunichar wc;
+ GList *result = NULL;
+ char *last_para = text;
+
+ while (*p)
+ {
+ wc = g_utf8_get_char (p);
+ next = g_utf8_next_char (p);
+ if (wc == (gunichar)-1)
+ {
+ fprintf (stderr, "%s: Invalid character in input\n", g_get_prgname ());
+ g_list_foreach (result, (GFunc)g_free, NULL);
+ return NULL;
+ }
+ if (!*p || !wc || wc == '\n')
+ {
+ Paragraph *para = g_new (Paragraph, 1);
+ para->text = last_para;
+ para->length = p - last_para;
+ para->layout = pango_layout_new (context);
+ pango_layout_set_text (para->layout, para->text, para->length);
+ para->height = 0;
+
+ last_para = next;
+
+ result = g_list_prepend (result, para);
+ }
+ if (!wc) /* incomplete character at end */
+ break;
+ p = next;
+ }
+
+ return g_list_reverse (result);
+}
+
+/* Given an x-y position, return the paragraph and offset
+ * within the paragraph of the click.
+ */
+gboolean
+xy_to_cp (int width, int x, int y, Paragraph **para_return, int *index)
+{
+ GList *para_list;
+ int height = 0;
+
+ *para_return = NULL;
+
+ PING();
+ para_list = paragraphs;
+ while (para_list && height < y)
+ {
+ Paragraph *para = para_list->data;
+
+ if (height + para->height >= y)
+ {
+ gboolean result = pango_layout_xy_to_index (para->layout, x * 1000, (y - height) * 1000,
+ index, NULL);
+ if (result && para_return)
+ *para_return = para;
+
+ return result;
+ }
+
+ height += para->height;
+ para_list = para_list->next;
+ }
+ PING();
+
+ return FALSE;
+}
+
+/* Given a paragraph and offset in that paragraph, find the
+ * bounding rectangle for the character at the offset.
+ */
+void
+char_bounds (Paragraph *para, int index, int width, PangoRectangle *rect)
+{
+ GList *para_list;
+
+ int height = 0;
+
+ para_list = paragraphs;
+ while (para_list)
+ {
+ Paragraph *cur_para = para_list->data;
+
+ if (cur_para == para)
+ {
+ PangoRectangle pos;
+
+ pango_layout_index_to_pos (cur_para->layout, index, &pos);
+
+ rect->x = MIN (pos.x, pos.x + pos.width) / 1000;
+ rect->width = ABS (pos.width) / 1000;
+ rect->y = height + pos.y / 1000;
+ rect->height = pos.height / 1000;
+ }
+
+ height += cur_para->height;
+ para_list = para_list->next;
+ }
+}
+
+/* XOR a rectangle over a given character
+ */
+void
+xor_char (GtkWidget *layout, GdkRectangle *clip_rect,
+ Paragraph *para, int offset)
+{
+ static GdkGC *gc;
+ PangoRectangle rect; /* GdkRectangle in 1.2 is too limited
+ */
+ if (!gc)
+ {
+ GdkGCValues values;
+ values.foreground = layout->style->white.pixel ?
+ layout->style->white : layout->style->black;
+ values.function = GDK_XOR;
+ gc = gdk_gc_new_with_values (GTK_LAYOUT (layout)->bin_window,
+ &values,
+ GDK_GC_FOREGROUND | GDK_GC_FUNCTION);
+ }
+
+ gdk_gc_set_clip_rectangle (gc, clip_rect);
+
+ char_bounds (para, offset, layout->allocation.width, &rect);
+
+ rect.y -= GTK_LAYOUT (layout)->yoffset;
+
+ if ((rect.y + rect.height >= 0) && (rect.y < layout->allocation.height))
+ gdk_draw_rectangle (GTK_LAYOUT (layout)->bin_window, gc, TRUE,
+ rect.x, rect.y, rect.width, rect.height);
+}
+
+/* Handle a size allocation by re-laying-out each paragraph to
+ * the new width, setting the new size for the layout and
+ * then queing a redraw
+ */
+void
+size_allocate (GtkWidget *layout, GtkAllocation *allocation)
+{
+ GList *tmp_list;
+ int height = 0;
+ PangoDirection base_dir = pango_context_get_base_dir (context);
+
+ PING();
+ tmp_list = paragraphs;
+ while (tmp_list)
+ {
+ Paragraph *para = tmp_list->data;
+ PangoRectangle logical_rect;
+
+ tmp_list = tmp_list->next;
+
+ pango_layout_set_alignment (para->layout,
+ base_dir == PANGO_DIRECTION_LTR ? PANGO_ALIGN_LEFT : PANGO_ALIGN_RIGHT);
+ pango_layout_set_width (para->layout, layout->allocation.width * 1000);
+
+ pango_layout_get_extents (para->layout, NULL, &logical_rect);
+ para->height = logical_rect.height / 1000;
+
+ height += para->height;
+ }
+
+ gtk_layout_set_size (GTK_LAYOUT (layout), allocation->width, height);
+
+ if (GTK_LAYOUT (layout)->yoffset + allocation->height > height)
+ gtk_adjustment_set_value (GTK_LAYOUT (layout)->vadjustment, height - allocation->height);
+}
+
+/* Handle a draw/expose by finding the paragraphs that intersect
+ * the region and reexposing them.
+ */
+void
+draw (GtkWidget *layout, GdkRectangle *area)
+{
+ GList *tmp_list;
+ int height = 0;
+
+ PING();
+ gdk_draw_rectangle (GTK_LAYOUT (layout)->bin_window,
+ layout->style->base_gc[layout->state],
+ TRUE,
+ area->x, area->y,
+ area->width, area->height);
+
+ gdk_gc_set_clip_rectangle (layout->style->text_gc[layout->state], area);
+
+ PING();
+ tmp_list = paragraphs;
+ while (tmp_list &&
+ height < area->y + area->height + GTK_LAYOUT (layout)->yoffset)
+ {
+ Paragraph *para = tmp_list->data;
+ tmp_list = tmp_list->next;
+
+ PING();
+ if (height + para->height >= GTK_LAYOUT (layout)->yoffset + area->y)
+ {
+ GdkGCValuesMask mask = GDK_GC_FOREGROUND|GDK_GC_BACKGROUND;
+ HDC hdc = gdk_win32_hdc_get (GDK_WINDOW_XWINDOW (GTK_LAYOUT (layout)->bin_window),
+ layout->style->text_gc[GTK_STATE_NORMAL],
+ mask);
+
+ pango_win32_render_layout (hdc, para->layout,
+ 0, height - GTK_LAYOUT (layout)->yoffset);
+
+ gdk_win32_hdc_release (GDK_WINDOW_XWINDOW (GTK_LAYOUT (layout)->bin_window),
+ layout->style->text_gc[GTK_STATE_NORMAL],
+ mask);
+ }
+
+ height += para->height;
+ }
+
+ PING();
+ gdk_gc_set_clip_rectangle (layout->style->text_gc[layout->state], NULL);
+
+ if (highlight_para)
+ xor_char (layout, area, highlight_para, highlight_offset);
+ PING();
+}
+
+gboolean
+expose (GtkWidget *layout, GdkEventExpose *event)
+{
+ PING();
+ if (event->window == GTK_LAYOUT (layout)->bin_window)
+ draw (layout, &event->area);
+
+ return TRUE;
+}
+
+void
+button_press (GtkWidget *layout, GdkEventButton *event)
+{
+ Paragraph *para = NULL;
+ int offset;
+ gchar *message;
+
+ PING();
+ xy_to_cp (layout->allocation.width,
+ event->x, event->y + GTK_LAYOUT (layout)->yoffset,
+ &para, &offset);
+
+ if (highlight_para)
+ xor_char (layout, NULL, highlight_para, highlight_offset);
+
+ highlight_para = para;
+ highlight_offset = offset;
+
+ if (para)
+ {
+ gunichar wc;
+
+ wc = g_utf8_get_char (para->text + offset);
+ message = g_strdup_printf ("Current char: U%04x", wc);
+
+ xor_char (layout, NULL, highlight_para, highlight_offset);
+ }
+ else
+ message = g_strdup_printf ("Current char:");
+
+ PING();
+ gtk_label_set_text (GTK_LABEL (message_label), message);
+ g_free (message);
+}
+
+static void
+checkbutton_toggled (GtkWidget *widget, gpointer data)
+{
+ GList *para_list;
+
+ PING();
+ pango_context_set_base_dir (context, GTK_TOGGLE_BUTTON (widget)->active ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR);
+
+ para_list = paragraphs;
+ while (para_list)
+ {
+ Paragraph *para = para_list->data;
+
+ pango_layout_context_changed (para->layout);
+ para_list = para_list->next;
+ }
+
+ gtk_widget_queue_resize (layout);
+}
+
+static void
+reload_font ()
+{
+ GList *para_list;
+
+ PING();
+ pango_context_set_font_description (context, &font_description);
+
+ para_list = paragraphs;
+ while (para_list)
+ {
+ Paragraph *para = para_list->data;
+
+ pango_layout_context_changed (para->layout);
+ para_list = para_list->next;
+ }
+
+ if (layout)
+ gtk_widget_queue_resize (layout);
+ PING();
+}
+
+void
+set_family (GtkWidget *entry, gpointer data)
+{
+ font_description.family_name = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1);
+ fill_styles_combo (styles_combo);
+}
+
+void
+set_style (GtkWidget *entry, gpointer data)
+{
+ char *str = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1);
+ PangoFontDescription *tmp_desc;
+
+ PING();
+ tmp_desc = pango_font_description_from_string (str);
+
+ font_description.style = tmp_desc->style;
+ font_description.variant = tmp_desc->variant;
+ font_description.weight = tmp_desc->weight;
+ font_description.stretch = tmp_desc->stretch;
+
+ pango_font_description_free (tmp_desc);
+ g_free (str);
+
+ reload_font ();
+}
+
+void
+font_size_changed (GtkAdjustment *adj)
+{
+ PING();
+ font_description.size = (int)(adj->value * PANGO_SCALE + 0.5);
+ reload_font();
+}
+
+static int
+compare_font_descriptions (const PangoFontDescription *a, const PangoFontDescription *b)
+{
+ int val = strcmp (a->family_name, b->family_name);
+ if (val != 0)
+ return val;
+
+ if (a->weight != b->weight)
+ return a->weight - b->weight;
+
+ if (a->style != b->style)
+ return a->style - b->style;
+
+ if (a->stretch != b->stretch)
+ return a->stretch - b->stretch;
+
+ if (a->variant != b->variant)
+ return a->variant - b->variant;
+
+ return 0;
+}
+
+static int
+font_description_sort_func (const void *a, const void *b)
+{
+ return compare_font_descriptions (*(PangoFontDescription **)a, *(PangoFontDescription **)b);
+}
+
+typedef struct
+{
+ PangoFontDescription **descs;
+ int n_descs;
+} FontDescInfo;
+
+static void
+free_info (FontDescInfo *info)
+{
+ pango_font_descriptions_free (info->descs, info->n_descs);
+}
+
+static void
+fill_styles_combo (GtkWidget *combo)
+{
+ int i;
+ GList *style_list = NULL;
+
+ FontDescInfo *info = g_new (FontDescInfo, 1);
+ PING();
+ pango_context_list_fonts (context, font_description.family_name, &info->descs, &info->n_descs);
+ gtk_object_set_data_full (GTK_OBJECT (combo), "descs", info, (GtkDestroyNotify)free_info);
+ PING();
+
+ qsort (info->descs, info->n_descs, sizeof(PangoFontDescription *), font_description_sort_func);
+
+ PING();
+ for (i=0; i<info->n_descs; i++)
+ {
+ char *str;
+
+ PangoFontDescription tmp_desc;
+
+ tmp_desc = *info->descs[i];
+ tmp_desc.family_name = NULL;
+ tmp_desc.size = 0;
+
+ str = pango_font_description_to_string (&tmp_desc);
+ style_list = g_list_prepend (style_list, str);
+ }
+
+ style_list = g_list_reverse (style_list);
+
+ PING();
+ gtk_combo_set_popdown_strings (GTK_COMBO (combo), style_list);
+ g_list_foreach (style_list, (GFunc)g_free, NULL);
+}
+
+static GtkWidget *
+make_styles_combo ()
+{
+ GtkWidget *combo;
+
+ PING();
+ combo = gtk_combo_new ();
+ gtk_combo_set_value_in_list (GTK_COMBO (combo), TRUE, FALSE);
+ gtk_editable_set_editable (GTK_EDITABLE (GTK_COMBO (combo)->entry), FALSE);
+
+ gtk_signal_connect (GTK_OBJECT (GTK_COMBO (combo)->entry), "changed",
+ GTK_SIGNAL_FUNC (set_style), NULL);
+
+ styles_combo = combo;
+ fill_styles_combo (combo);
+
+ PING();
+ return combo;
+}
+
+static int
+cmp_strings (const void *a, const void *b)
+{
+ return strcmp (*(const char **)a, *(const char **)b);
+}
+
+GtkWidget *
+make_families_menu ()
+{
+ GtkWidget *combo;
+ gchar **families;
+ int n_families;
+ GList *family_list = NULL;
+ int i;
+
+ PING();
+ pango_context_list_families (context, &families, &n_families);
+ qsort (families, n_families, sizeof(char *), cmp_strings);
+
+ PING();
+ for (i=0; i<n_families; i++)
+ family_list = g_list_prepend (family_list, families[i]);
+
+ family_list = g_list_reverse (family_list);
+
+ combo = gtk_combo_new ();
+ gtk_combo_set_popdown_strings (GTK_COMBO (combo), family_list);
+ gtk_combo_set_value_in_list (GTK_COMBO (combo), TRUE, FALSE);
+ gtk_editable_set_editable (GTK_EDITABLE (GTK_COMBO (combo)->entry), FALSE);
+
+ gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (combo)->entry), font_description.family_name);
+
+ gtk_signal_connect (GTK_OBJECT (GTK_COMBO (combo)->entry), "changed",
+ GTK_SIGNAL_FUNC (set_family), NULL);
+
+ g_list_free (family_list);
+ pango_font_map_free_families (families, n_families);
+
+ PING();
+ return combo;
+}
+
+
+GtkWidget *
+make_font_selector (void)
+{
+ GtkWidget *hbox;
+ GtkWidget *util_hbox;
+ GtkWidget *label;
+ GtkWidget *option_menu;
+ GtkWidget *spin_button;
+ GtkAdjustment *adj;
+
+ hbox = gtk_hbox_new (FALSE, 4);
+
+ util_hbox = gtk_hbox_new (FALSE, 2);
+ label = gtk_label_new ("Family:");
+ gtk_box_pack_start (GTK_BOX (util_hbox), label, FALSE, FALSE, 0);
+ option_menu = make_families_menu ();
+ gtk_box_pack_start (GTK_BOX (util_hbox), option_menu, FALSE, FALSE, 0);
+
+ gtk_box_pack_start (GTK_BOX (hbox), util_hbox, FALSE, FALSE, 0);
+
+ util_hbox = gtk_hbox_new (FALSE, 2);
+ label = gtk_label_new ("Style:");
+ gtk_box_pack_start (GTK_BOX (util_hbox), label, FALSE, FALSE, 0);
+ option_menu = make_styles_combo ();
+ gtk_box_pack_start (GTK_BOX (util_hbox), option_menu, FALSE, FALSE, 0);
+
+ gtk_box_pack_start (GTK_BOX (hbox), util_hbox, FALSE, FALSE, 0);
+
+ util_hbox = gtk_hbox_new (FALSE, 2);
+ label = gtk_label_new ("Size:");
+ gtk_box_pack_start (GTK_BOX (util_hbox), label, FALSE, FALSE, 0);
+ spin_button = gtk_spin_button_new (NULL, 1., 0);
+ gtk_box_pack_start (GTK_BOX (util_hbox), spin_button, FALSE, FALSE, 0);
+
+ gtk_box_pack_start (GTK_BOX (hbox), util_hbox, FALSE, FALSE, 0);
+
+ adj = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (spin_button));
+ adj->value = font_description.size / 1000.;
+ adj->lower = 0;
+ adj->upper = 1024;
+ adj->step_increment = 1;
+ adj->page_size = 10;
+ gtk_adjustment_changed (adj);
+ gtk_adjustment_value_changed (adj);
+
+ gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
+ GTK_SIGNAL_FUNC (font_size_changed), NULL);
+
+ return hbox;
+}
+
+int
+main (int argc, char **argv)
+{
+ char *text;
+ GtkWidget *window;
+ GtkWidget *scrollwin;
+ GtkWidget *vbox, *hbox;
+ GtkWidget *frame;
+ GtkWidget *checkbutton;
+
+ gtk_init (&argc, &argv);
+
+ if (argc != 2)
+ {
+ fprintf (stderr, "Usage: %s FILE\n", g_get_prgname ());
+ exit(1);
+ }
+
+ /* Create the list of paragraphs from the supplied file
+ */
+ text = read_file (argv[1]);
+ if (!text)
+ exit(1);
+
+ context = pango_win32_get_context ();
+
+ paragraphs = split_paragraphs (text);
+
+ pango_context_set_lang (context, "en_US");
+ pango_context_set_base_dir (context, PANGO_DIRECTION_LTR);
+
+ font_description.family_name = g_strdup ("sans");
+ font_description.style = PANGO_STYLE_NORMAL;
+ font_description.variant = PANGO_VARIANT_NORMAL;
+ font_description.weight = 500;
+ font_description.stretch = PANGO_STRETCH_NORMAL;
+ font_description.size = 16000;
+
+ pango_context_set_font_description (context, &font_description);
+
+ /* Create the user interface
+ */
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_default_size (GTK_WINDOW (window), 400, 400);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
+
+ vbox = gtk_vbox_new (FALSE, 4);
+ gtk_container_add (GTK_CONTAINER (window), vbox);
+
+ hbox = make_font_selector ();
+ gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+
+ scrollwin = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrollwin),
+ GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+
+ gtk_box_pack_start (GTK_BOX (vbox), scrollwin, TRUE, TRUE, 0);
+
+ layout = gtk_layout_new (NULL, NULL);
+ gtk_widget_set_events (layout, GDK_BUTTON_PRESS_MASK);
+ gtk_widget_set_app_paintable (layout, TRUE);
+
+ gtk_signal_connect (GTK_OBJECT (layout), "size_allocate",
+ GTK_SIGNAL_FUNC (size_allocate), paragraphs);
+ gtk_signal_connect (GTK_OBJECT (layout), "expose_event",
+ GTK_SIGNAL_FUNC (expose), paragraphs);
+ gtk_signal_connect (GTK_OBJECT (layout), "draw",
+ GTK_SIGNAL_FUNC (draw), paragraphs);
+ gtk_signal_connect (GTK_OBJECT (layout), "button_press_event",
+ GTK_SIGNAL_FUNC (button_press), paragraphs);
+
+ gtk_container_add (GTK_CONTAINER (scrollwin), layout);
+
+ frame = gtk_frame_new (NULL);
+ gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
+ gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
+
+ PING();
+ message_label = gtk_label_new ("Current char:");
+ gtk_misc_set_padding (GTK_MISC (message_label), 1, 1);
+ gtk_misc_set_alignment (GTK_MISC (message_label), 0.0, 0.5);
+ gtk_container_add (GTK_CONTAINER (frame), message_label);
+
+ checkbutton = gtk_check_button_new_with_label ("Use RTL global direction");
+ gtk_signal_connect (GTK_OBJECT (checkbutton), "toggled",
+ GTK_SIGNAL_FUNC (checkbutton_toggled), NULL);
+ gtk_box_pack_start (GTK_BOX (vbox), checkbutton, FALSE, FALSE, 0);
+
+ gtk_widget_show_all (window);
+
+ PING();
+ gtk_main ();
+
+ return 0;
+}