3 * The GtkTextView widget displays a GtkTextBuffer. One GtkTextBuffer
4 * can be displayed by multiple GtkTextViews. This demo has two views
5 * displaying a single buffer, and shows off the widget's text
11 #include <stdlib.h> /* for exit() */
13 #define gray50_width 2
14 #define gray50_height 2
15 static char gray50_bits[] = {
20 create_tags (GtkTextBuffer *buffer)
24 /* Create a bunch of tags. Note that it's also possible to
25 * create tags with gtk_text_tag_new() then add them to the
26 * tag table for the buffer, gtk_text_buffer_create_tag() is
27 * just a convenience function. Also note that you don't have
28 * to give tags a name; pass NULL for the name to create an
31 * In any real app, another useful optimization would be to create
32 * a GtkTextTagTable in advance, and reuse the same tag table for
33 * all the buffers with the same tag set, instead of creating
34 * new copies of the same tags for every buffer.
36 * Tags are assigned default priorities in order of addition to the
37 * tag table. That is, tags created later that affect the same text
38 * property affected by an earlier tag will override the earlier
39 * tag. You can modify tag priorities with
40 * gtk_text_tag_set_priority().
43 gtk_text_buffer_create_tag (buffer, "heading",
44 "weight", PANGO_WEIGHT_BOLD,
45 "size", 15 * PANGO_SCALE,
48 gtk_text_buffer_create_tag (buffer, "italic",
49 "style", PANGO_STYLE_ITALIC, NULL);
51 gtk_text_buffer_create_tag (buffer, "bold",
52 "weight", PANGO_WEIGHT_BOLD, NULL);
54 gtk_text_buffer_create_tag (buffer, "big",
55 /* points times the PANGO_SCALE factor */
56 "size", 20 * PANGO_SCALE, NULL);
58 gtk_text_buffer_create_tag (buffer, "xx-small",
59 "scale", PANGO_SCALE_XX_SMALL, NULL);
61 gtk_text_buffer_create_tag (buffer, "x-large",
62 "scale", PANGO_SCALE_X_LARGE, NULL);
64 gtk_text_buffer_create_tag (buffer, "monospace",
65 "family", "monospace", NULL);
67 gtk_text_buffer_create_tag (buffer, "blue_foreground",
68 "foreground", "blue", NULL);
70 gtk_text_buffer_create_tag (buffer, "red_background",
71 "background", "red", NULL);
73 stipple = gdk_bitmap_create_from_data (NULL,
74 gray50_bits, gray50_width,
77 gtk_text_buffer_create_tag (buffer, "background_stipple",
78 "background_stipple", stipple, NULL);
80 gtk_text_buffer_create_tag (buffer, "foreground_stipple",
81 "foreground_stipple", stipple, NULL);
83 g_object_unref (G_OBJECT (stipple));
85 gtk_text_buffer_create_tag (buffer, "big_gap_before_line",
86 "pixels_above_lines", 30, NULL);
88 gtk_text_buffer_create_tag (buffer, "big_gap_after_line",
89 "pixels_below_lines", 30, NULL);
91 gtk_text_buffer_create_tag (buffer, "double_spaced_line",
92 "pixels_inside_wrap", 10, NULL);
94 gtk_text_buffer_create_tag (buffer, "not_editable",
95 "editable", FALSE, NULL);
97 gtk_text_buffer_create_tag (buffer, "word_wrap",
98 "wrap_mode", GTK_WRAP_WORD, NULL);
100 gtk_text_buffer_create_tag (buffer, "char_wrap",
101 "wrap_mode", GTK_WRAP_CHAR, NULL);
103 gtk_text_buffer_create_tag (buffer, "no_wrap",
104 "wrap_mode", GTK_WRAP_NONE, NULL);
106 gtk_text_buffer_create_tag (buffer, "center",
107 "justification", GTK_JUSTIFY_CENTER, NULL);
109 gtk_text_buffer_create_tag (buffer, "right_justify",
110 "justification", GTK_JUSTIFY_RIGHT, NULL);
112 gtk_text_buffer_create_tag (buffer, "wide_margins",
113 "left_margin", 50, "right_margin", 50,
116 gtk_text_buffer_create_tag (buffer, "strikethrough",
117 "strikethrough", TRUE, NULL);
119 gtk_text_buffer_create_tag (buffer, "underline",
120 "underline", PANGO_UNDERLINE_SINGLE, NULL);
122 gtk_text_buffer_create_tag (buffer, "double_underline",
123 "underline", PANGO_UNDERLINE_DOUBLE, NULL);
125 gtk_text_buffer_create_tag (buffer, "superscript",
126 "rise", 10 * PANGO_SCALE, /* 10 pixels */
127 "size", 8 * PANGO_SCALE, /* 8 points */
130 gtk_text_buffer_create_tag (buffer, "subscript",
131 "rise", -10 * PANGO_SCALE, /* 10 pixels */
132 "size", 8 * PANGO_SCALE, /* 8 points */
135 gtk_text_buffer_create_tag (buffer, "rtl_quote",
136 "wrap_mode", GTK_WRAP_WORD,
137 "direction", GTK_TEXT_DIR_RTL,
145 insert_text (GtkTextBuffer *buffer)
148 GtkTextIter start, end;
151 GtkTextChildAnchor *anchor;
153 pixbuf = gdk_pixbuf_new_from_file ("./gtk-logo-rgb.gif", NULL);
155 gdk_pixbuf_new_from_file (DEMOCODEDIR"/gtk-logo-rgb.gif", NULL);
159 g_printerr ("Failed to load image file gtk-logo-rgb.gif\n");
163 scaled = gdk_pixbuf_scale_simple (pixbuf, 32, 32, GDK_INTERP_BILINEAR);
164 g_object_unref (G_OBJECT (pixbuf));
167 /* get start of buffer; each insertion will revalidate the
168 * iterator to point to just after the inserted text.
170 gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0);
172 gtk_text_buffer_insert (buffer, &iter, "The text widget can display text with all kinds of nifty attributes. It also supports multiple views of the same buffer; this demo is showing the same buffer in two places.\n\n", -1);
174 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, "Font styles. ", -1,
177 gtk_text_buffer_insert (buffer, &iter, "For example, you can have ", -1);
178 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
181 gtk_text_buffer_insert (buffer, &iter, ", ", -1);
182 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
185 gtk_text_buffer_insert (buffer, &iter, ", or ", -1);
186 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
187 "monospace (typewriter)", -1,
189 gtk_text_buffer_insert (buffer, &iter, ", or ", -1);
190 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
193 gtk_text_buffer_insert (buffer, &iter, " text. ", -1);
194 gtk_text_buffer_insert (buffer, &iter, "It's best not to hardcode specific text sizes; you can use relative sizes as with CSS, such as ", -1);
195 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
198 gtk_text_buffer_insert (buffer, &iter, " or ", -1);
199 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
202 gtk_text_buffer_insert (buffer, &iter, " to ensure that your program properly adapts if the user changes the default font size.\n\n", -1);
204 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, "Colors. ", -1,
207 gtk_text_buffer_insert (buffer, &iter, "Colors such as ", -1);
208 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
209 "a blue foreground", -1,
210 "blue_foreground", NULL);
211 gtk_text_buffer_insert (buffer, &iter, " or ", -1);
212 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
213 "a red background", -1,
214 "red_background", NULL);
215 gtk_text_buffer_insert (buffer, &iter, " or even ", -1);
216 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
217 "a stippled red background", -1,
219 "background_stipple",
222 gtk_text_buffer_insert (buffer, &iter, " or ", -1);
223 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
224 "a stippled blue foreground on solid red background", -1,
227 "foreground_stipple",
229 gtk_text_buffer_insert (buffer, &iter, " (select that to read it) can be used.\n\n", -1);
231 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, "Underline, strikethrough, and rise. ", -1,
234 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
236 "strikethrough", NULL);
237 gtk_text_buffer_insert (buffer, &iter, ", ", -1);
238 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
241 gtk_text_buffer_insert (buffer, &iter, ", ", -1);
242 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
243 "double underline", -1,
244 "double_underline", NULL);
245 gtk_text_buffer_insert (buffer, &iter, ", ", -1);
246 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
248 "superscript", NULL);
249 gtk_text_buffer_insert (buffer, &iter, ", and ", -1);
250 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
253 gtk_text_buffer_insert (buffer, &iter, " are all supported.\n\n", -1);
255 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, "Images. ", -1,
258 gtk_text_buffer_insert (buffer, &iter, "The buffer can have images in it: ", -1);
259 gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf);
260 gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf);
261 gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf);
262 gtk_text_buffer_insert (buffer, &iter, " for example.\n\n", -1);
264 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, "Spacing. ", -1,
267 gtk_text_buffer_insert (buffer, &iter, "You can adjust the amount of space before each line.\n", -1);
269 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
270 "This line has a whole lot of space before it.\n", -1,
271 "big_gap_before_line", "wide_margins", NULL);
272 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
273 "You can also adjust the amount of space after each line; this line has a whole lot of space after it.\n", -1,
274 "big_gap_after_line", "wide_margins", NULL);
276 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
277 "You can also adjust the amount of space between wrapped lines; this line has extra space between each wrapped line in the same paragraph. To show off wrapping, some filler text: the quick brown fox jumped over the lazy dog. Blah blah blah blah blah blah blah blah blah.\n", -1,
278 "double_spaced_line", "wide_margins", NULL);
280 gtk_text_buffer_insert (buffer, &iter, "Also note that those lines have extra-wide margins.\n\n", -1);
282 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, "Editability. ", -1,
285 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
286 "This line is 'locked down' and can't be edited by the user - just try it! You can't delete this line.\n\n", -1,
287 "not_editable", NULL);
289 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, "Wrapping. ", -1,
292 gtk_text_buffer_insert (buffer, &iter,
293 "This line (and most of the others in this buffer) is word-wrapped, using the proper Unicode algorithm. Word wrap should work in all scripts and languages that GTK+ supports. Let's make this a long paragraph to demonstrate: blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah\n\n", -1);
295 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
296 "This line has character-based wrapping, and can wrap between any two character glyphs. Let's make this a long paragraph to demonstrate: blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah\n\n", -1,
299 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
300 "This line has all wrapping turned off, so it makes the horizontal scrollbar appear.\n\n\n", -1,
303 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, "Justification. ", -1,
306 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
307 "\nThis line has center justification.\n", -1,
310 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
311 "This line has right justification.\n", -1,
312 "right_justify", NULL);
314 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
315 "\nThis line has big wide margins. Text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text.\n", -1,
316 "wide_margins", NULL);
318 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, "Internationalization. ", -1,
321 gtk_text_buffer_insert (buffer, &iter,
322 "You can put all sorts of Unicode text in the buffer.\n\nGerman (Deutsch Süd) Grüß Gott\nGreek (Ελληνικά) Γειά σας\nHebrew שלום\nJapanese (日本語)\n\nThe widget properly handles bidirectional text, word wrapping, DOS/UNIX/Unicode paragraph separators, grapheme boundaries, and so on using the Pango internationalization framework.\n", -1);
324 gtk_text_buffer_insert (buffer, &iter, "Here's a word-wrapped quote in a right-to-left language:\n", -1);
325 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, "وقد بدأ ثلاث من أكثر المؤسسات تقدما في شبكة اكسيون برامجها كمنظمات لا تسعى للربح، ثم تحولت في السنوات الخمس الماضية إلى مؤسسات مالية منظمة، وباتت جزءا من النظام المالي في بلدانها، ولكنها تتخصص في خدمة قطاع المشروعات الصغيرة. وأحد أكثر هذه المؤسسات نجاحا هو »بانكوسول« في بوليفيا.\n\n", -1,
328 gtk_text_buffer_insert (buffer, &iter, "You can put widgets in the buffer: Here's a button: ", -1);
329 anchor = gtk_text_buffer_create_child_anchor (buffer, &iter);
330 gtk_text_buffer_insert (buffer, &iter, " and a menu: ", -1);
331 anchor = gtk_text_buffer_create_child_anchor (buffer, &iter);
332 gtk_text_buffer_insert (buffer, &iter, " and a scale: ", -1);
333 anchor = gtk_text_buffer_create_child_anchor (buffer, &iter);
334 gtk_text_buffer_insert (buffer, &iter, " and an animation: ", -1);
335 anchor = gtk_text_buffer_create_child_anchor (buffer, &iter);
336 gtk_text_buffer_insert (buffer, &iter, " finally a text entry: ", -1);
337 anchor = gtk_text_buffer_create_child_anchor (buffer, &iter);
338 gtk_text_buffer_insert (buffer, &iter, ".\n", -1);
340 gtk_text_buffer_insert (buffer, &iter, "\n\nThis demo doesn't demonstrate all the GtkTextBuffer features; it leaves out, for example: invisible/hidden text (doesn't work in GTK 2, but planned), tab stops, application-drawn areas on the sides of the widget for displaying breakpoints and such...", -1);
342 /* Apply word_wrap tag to whole buffer */
343 gtk_text_buffer_get_bounds (buffer, &start, &end);
344 gtk_text_buffer_apply_tag_by_name (buffer, "word_wrap", &start, &end);
346 g_object_unref (G_OBJECT (pixbuf));
350 find_anchor (GtkTextIter *iter)
352 while (gtk_text_iter_forward_char (iter))
354 if (gtk_text_iter_get_child_anchor (iter))
361 attach_widgets (GtkTextView *text_view)
364 GtkTextBuffer *buffer;
367 buffer = gtk_text_view_get_buffer (text_view);
369 gtk_text_buffer_get_start_iter (buffer, &iter);
372 while (find_anchor (&iter))
374 GtkTextChildAnchor *anchor;
377 anchor = gtk_text_iter_get_child_anchor (&iter);
381 widget = gtk_button_new_with_label ("Click Me");
385 GtkWidget *menu_item;
388 menu = gtk_menu_new ();
390 widget = gtk_option_menu_new ();
392 menu_item = gtk_menu_item_new_with_label ("Option 1");
393 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
394 menu_item = gtk_menu_item_new_with_label ("Option 2");
395 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
396 menu_item = gtk_menu_item_new_with_label ("Option 3");
397 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
399 gtk_option_menu_set_menu (GTK_OPTION_MENU (widget), menu);
403 widget = gtk_hscale_new (NULL);
404 gtk_range_set_range (GTK_RANGE (widget), 0, 100);
405 gtk_widget_set_size_request (widget, 70, -1);
409 if (g_file_test ("./floppybuddy.gif", G_FILE_TEST_EXISTS))
410 widget = gtk_image_new_from_file ("./floppybuddy.gif");
412 widget = gtk_image_new_from_file (DEMOCODEDIR"/floppybuddy.gif");
416 widget = gtk_entry_new ();
420 widget = NULL; /* avoids a compiler warning */
421 g_assert_not_reached ();
424 gtk_text_view_add_child_at_anchor (text_view,
428 gtk_widget_show_all (widget);
437 static GtkWidget *window = NULL;
445 GtkTextBuffer *buffer;
447 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
448 gtk_window_set_default_size (GTK_WINDOW (window),
451 g_signal_connect (window, "destroy",
452 G_CALLBACK (gtk_widget_destroyed), &window);
454 gtk_window_set_title (GTK_WINDOW (window), "TextView");
455 gtk_container_set_border_width (GTK_CONTAINER (window), 0);
457 vpaned = gtk_vpaned_new ();
458 gtk_container_set_border_width (GTK_CONTAINER(vpaned), 5);
459 gtk_container_add (GTK_CONTAINER (window), vpaned);
461 /* For convenience, we just use the autocreated buffer from
462 * the first text view; you could also create the buffer
463 * by itself with gtk_text_buffer_new(), then later create
466 view1 = gtk_text_view_new ();
467 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view1));
468 view2 = gtk_text_view_new_with_buffer (buffer);
470 sw = gtk_scrolled_window_new (NULL, NULL);
471 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
472 GTK_POLICY_AUTOMATIC,
473 GTK_POLICY_AUTOMATIC);
474 gtk_paned_add1 (GTK_PANED (vpaned), sw);
476 gtk_container_add (GTK_CONTAINER (sw), view1);
478 sw = gtk_scrolled_window_new (NULL, NULL);
479 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
480 GTK_POLICY_AUTOMATIC,
481 GTK_POLICY_AUTOMATIC);
482 gtk_paned_add2 (GTK_PANED (vpaned), sw);
484 gtk_container_add (GTK_CONTAINER (sw), view2);
486 create_tags (buffer);
487 insert_text (buffer);
489 attach_widgets (GTK_TEXT_VIEW (view1));
490 attach_widgets (GTK_TEXT_VIEW (view2));
492 gtk_widget_show_all (vpaned);
495 if (!GTK_WIDGET_VISIBLE (window))
497 gtk_widget_show (window);
501 gtk_widget_destroy (window);