2015-07-29 23:07:56 +00:00
|
|
|
|
/* Text View/Hypertext
|
2020-09-13 18:59:33 +00:00
|
|
|
|
* #Keywords: GtkTextView, GtkTextBuffer
|
2003-08-05 19:16:01 +00:00
|
|
|
|
*
|
2011-09-02 03:55:47 +00:00
|
|
|
|
* Usually, tags modify the appearance of text in the view, e.g. making it
|
|
|
|
|
* bold or colored or underlined. But tags are not restricted to appearance.
|
|
|
|
|
* They can also affect the behavior of mouse and key presses, as this demo
|
2003-11-08 22:08:05 +00:00
|
|
|
|
* shows.
|
2020-09-17 02:31:34 +00:00
|
|
|
|
*
|
|
|
|
|
* We also demonstrate adding other things to a text view, such as
|
|
|
|
|
* clickable icons.
|
2003-08-05 19:16:01 +00:00
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <gtk/gtk.h>
|
|
|
|
|
#include <gdk/gdkkeysyms.h>
|
|
|
|
|
|
|
|
|
|
/* Inserts a piece of text into the buffer, giving it the usual
|
|
|
|
|
* appearance of a hyperlink in a web browser: blue and underlined.
|
|
|
|
|
* Additionally, attaches some data on the tag, to make it recognizable
|
2011-09-02 03:55:47 +00:00
|
|
|
|
* as a link.
|
2003-08-05 19:16:01 +00:00
|
|
|
|
*/
|
2011-09-02 03:55:47 +00:00
|
|
|
|
static void
|
|
|
|
|
insert_link (GtkTextBuffer *buffer,
|
|
|
|
|
GtkTextIter *iter,
|
2020-03-07 14:01:21 +00:00
|
|
|
|
const char *text,
|
2020-07-24 13:54:49 +00:00
|
|
|
|
int page)
|
2003-08-05 19:16:01 +00:00
|
|
|
|
{
|
|
|
|
|
GtkTextTag *tag;
|
2011-09-02 03:55:47 +00:00
|
|
|
|
|
|
|
|
|
tag = gtk_text_buffer_create_tag (buffer, NULL,
|
|
|
|
|
"foreground", "blue",
|
|
|
|
|
"underline", PANGO_UNDERLINE_SINGLE,
|
2008-07-06 07:24:02 +00:00
|
|
|
|
NULL);
|
2003-08-05 19:16:01 +00:00
|
|
|
|
g_object_set_data (G_OBJECT (tag), "page", GINT_TO_POINTER (page));
|
|
|
|
|
gtk_text_buffer_insert_with_tags (buffer, iter, text, -1, tag, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-17 02:31:34 +00:00
|
|
|
|
/* Quick-and-dirty text-to-speech for a single word. If you don't hear
|
|
|
|
|
* anything, you are missing espeak-ng on your system.
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
say_word (GtkGestureClick *gesture,
|
|
|
|
|
guint n_press,
|
|
|
|
|
double x,
|
|
|
|
|
double y,
|
|
|
|
|
const char *word)
|
|
|
|
|
{
|
|
|
|
|
const char *argv[3];
|
|
|
|
|
|
|
|
|
|
argv[0] = "espeak-ng";
|
|
|
|
|
argv[1] = word;
|
|
|
|
|
argv[2] = NULL;
|
|
|
|
|
|
|
|
|
|
g_spawn_async (NULL, (char **)argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
2003-08-05 19:16:01 +00:00
|
|
|
|
/* Fills the buffer with text and interspersed links. In any real
|
|
|
|
|
* hypertext app, this method would parse a file to identify the links.
|
|
|
|
|
*/
|
|
|
|
|
static void
|
2020-09-17 02:31:34 +00:00
|
|
|
|
show_page (GtkTextView *text_view,
|
|
|
|
|
int page)
|
2003-08-05 19:16:01 +00:00
|
|
|
|
{
|
2020-09-17 02:31:34 +00:00
|
|
|
|
GtkTextBuffer *buffer;
|
2003-08-05 19:16:01 +00:00
|
|
|
|
GtkTextIter iter;
|
2020-09-17 02:31:34 +00:00
|
|
|
|
GtkWidget *child;
|
|
|
|
|
GtkTextChildAnchor *anchor;
|
|
|
|
|
GtkEventController *controller;
|
2003-08-05 19:16:01 +00:00
|
|
|
|
|
2020-09-17 02:31:34 +00:00
|
|
|
|
buffer = gtk_text_view_get_buffer (text_view);
|
2003-08-05 19:16:01 +00:00
|
|
|
|
gtk_text_buffer_set_text (buffer, "", 0);
|
|
|
|
|
gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0);
|
2019-11-01 18:30:33 +00:00
|
|
|
|
gtk_text_buffer_begin_irreversible_action (buffer);
|
2003-08-05 19:16:01 +00:00
|
|
|
|
if (page == 1)
|
|
|
|
|
{
|
2020-09-17 02:31:34 +00:00
|
|
|
|
GtkIconPaintable *icon;
|
|
|
|
|
GtkIconTheme *theme;
|
|
|
|
|
|
2003-08-05 19:16:01 +00:00
|
|
|
|
gtk_text_buffer_insert (buffer, &iter, "Some text to show that simple ", -1);
|
2020-09-17 02:31:34 +00:00
|
|
|
|
insert_link (buffer, &iter, "hypertext", 3);
|
2003-08-05 19:16:01 +00:00
|
|
|
|
gtk_text_buffer_insert (buffer, &iter, " can easily be realized with ", -1);
|
|
|
|
|
insert_link (buffer, &iter, "tags", 2);
|
2020-09-17 02:31:34 +00:00
|
|
|
|
gtk_text_buffer_insert (buffer, &iter, ".\n", -1);
|
|
|
|
|
gtk_text_buffer_insert (buffer, &iter,
|
|
|
|
|
"Of course you can also embed Emoji 😋, "
|
|
|
|
|
"icons ", -1);
|
|
|
|
|
|
|
|
|
|
theme = gtk_icon_theme_get_for_display (gtk_widget_get_display (GTK_WIDGET (text_view)));
|
|
|
|
|
icon = gtk_icon_theme_lookup_icon (theme,
|
|
|
|
|
"microphone-sensitivity-high-symbolic",
|
|
|
|
|
NULL,
|
|
|
|
|
16,
|
|
|
|
|
1,
|
|
|
|
|
GTK_TEXT_DIR_LTR,
|
|
|
|
|
0);
|
|
|
|
|
gtk_text_buffer_insert_paintable (buffer, &iter, GDK_PAINTABLE (icon));
|
|
|
|
|
g_object_unref (icon);
|
|
|
|
|
gtk_text_buffer_insert (buffer, &iter, ", or even widgets ", -1);
|
|
|
|
|
anchor = gtk_text_buffer_create_child_anchor (buffer, &iter);
|
|
|
|
|
child = gtk_level_bar_new_for_interval (0, 100);
|
|
|
|
|
gtk_level_bar_set_value (GTK_LEVEL_BAR (child), 50);
|
|
|
|
|
gtk_widget_set_size_request (child, 100, -1);
|
|
|
|
|
gtk_text_view_add_child_at_anchor (text_view, child, anchor);
|
2003-08-05 19:16:01 +00:00
|
|
|
|
gtk_text_buffer_insert (buffer, &iter, ".", -1);
|
|
|
|
|
}
|
|
|
|
|
else if (page == 2)
|
|
|
|
|
{
|
2020-09-17 02:31:34 +00:00
|
|
|
|
GtkTextTag *tag;
|
|
|
|
|
|
|
|
|
|
tag = gtk_text_buffer_create_tag (buffer, NULL,
|
|
|
|
|
"weight", PANGO_WEIGHT_BOLD,
|
|
|
|
|
"scale", PANGO_SCALE_X_LARGE,
|
|
|
|
|
NULL);
|
|
|
|
|
gtk_text_buffer_insert_with_tags (buffer, &iter, "tag", -1, tag, NULL);
|
|
|
|
|
tag = gtk_text_buffer_create_tag (buffer, NULL,
|
|
|
|
|
"family", "monospace",
|
|
|
|
|
NULL);
|
|
|
|
|
gtk_text_buffer_insert_with_tags (buffer, &iter, " / tag / ", -1, tag, NULL);
|
|
|
|
|
|
|
|
|
|
anchor = gtk_text_buffer_create_child_anchor (buffer, &iter);
|
|
|
|
|
child = gtk_image_new_from_icon_name ("audio-volume-high-symbolic");
|
|
|
|
|
gtk_widget_set_cursor_from_name (child, "pointer");
|
|
|
|
|
controller = GTK_EVENT_CONTROLLER (gtk_gesture_click_new ());
|
|
|
|
|
g_signal_connect (controller, "pressed", G_CALLBACK (say_word), (gpointer)"tag");
|
|
|
|
|
gtk_widget_add_controller (child, controller);
|
|
|
|
|
gtk_text_view_add_child_at_anchor (text_view, child, anchor);
|
|
|
|
|
|
|
|
|
|
gtk_text_buffer_insert (buffer, &iter, "\n"
|
|
|
|
|
"An attribute that can be applied to some range of text. For example, "
|
|
|
|
|
"a tag might be called “bold” and make the text inside the tag bold.\n"
|
|
|
|
|
"However, the tag concept is more general than that; "
|
|
|
|
|
"tags don't have to affect appearance. They can instead affect the "
|
|
|
|
|
"behavior of mouse and key presses, “lock” a range of text so the "
|
|
|
|
|
"user can't edit it, or countless other things.\n", -1);
|
2003-08-05 19:16:01 +00:00
|
|
|
|
insert_link (buffer, &iter, "Go back", 1);
|
|
|
|
|
}
|
2011-09-02 03:55:47 +00:00
|
|
|
|
else if (page == 3)
|
2003-08-05 19:16:01 +00:00
|
|
|
|
{
|
|
|
|
|
GtkTextTag *tag;
|
2011-09-02 03:55:47 +00:00
|
|
|
|
|
|
|
|
|
tag = gtk_text_buffer_create_tag (buffer, NULL,
|
|
|
|
|
"weight", PANGO_WEIGHT_BOLD,
|
2020-09-17 02:31:34 +00:00
|
|
|
|
"scale", PANGO_SCALE_X_LARGE,
|
2008-07-06 07:24:02 +00:00
|
|
|
|
NULL);
|
2020-09-17 02:31:34 +00:00
|
|
|
|
gtk_text_buffer_insert_with_tags (buffer, &iter, "hypertext", -1, tag, NULL);
|
|
|
|
|
tag = gtk_text_buffer_create_tag (buffer, NULL,
|
|
|
|
|
"family", "monospace",
|
|
|
|
|
NULL);
|
|
|
|
|
gtk_text_buffer_insert_with_tags (buffer, &iter, " / ˈhaɪ pərˌtɛkst / ", -1, tag, NULL);
|
|
|
|
|
|
|
|
|
|
anchor = gtk_text_buffer_create_child_anchor (buffer, &iter);
|
|
|
|
|
child = gtk_image_new_from_icon_name ("audio-volume-high-symbolic");
|
|
|
|
|
gtk_widget_set_cursor_from_name (child, "pointer");
|
|
|
|
|
controller = GTK_EVENT_CONTROLLER (gtk_gesture_click_new ());
|
|
|
|
|
g_signal_connect (controller, "pressed", G_CALLBACK (say_word), (gpointer)"hypertext");
|
|
|
|
|
gtk_widget_add_controller (child, controller);
|
|
|
|
|
gtk_text_view_add_child_at_anchor (text_view, child, anchor);
|
|
|
|
|
|
|
|
|
|
gtk_text_buffer_insert (buffer, &iter, "\n"
|
|
|
|
|
"Machine-readable text that is not sequential but is organized "
|
|
|
|
|
"so that related items of information are connected.\n", -1);
|
2003-08-05 19:16:01 +00:00
|
|
|
|
insert_link (buffer, &iter, "Go back", 1);
|
|
|
|
|
}
|
2019-11-01 18:30:33 +00:00
|
|
|
|
gtk_text_buffer_end_irreversible_action (buffer);
|
2003-08-05 19:16:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2011-09-02 03:55:47 +00:00
|
|
|
|
/* Looks at all tags covering the position of iter in the text view,
|
2003-08-05 19:16:01 +00:00
|
|
|
|
* and if one of them is a link, follow it by showing the page identified
|
|
|
|
|
* by the data attached to it.
|
|
|
|
|
*/
|
|
|
|
|
static void
|
2011-09-02 03:55:47 +00:00
|
|
|
|
follow_if_link (GtkWidget *text_view,
|
2008-07-06 07:24:02 +00:00
|
|
|
|
GtkTextIter *iter)
|
2003-08-05 19:16:01 +00:00
|
|
|
|
{
|
|
|
|
|
GSList *tags = NULL, *tagp = NULL;
|
|
|
|
|
|
|
|
|
|
tags = gtk_text_iter_get_tags (iter);
|
|
|
|
|
for (tagp = tags; tagp != NULL; tagp = tagp->next)
|
|
|
|
|
{
|
|
|
|
|
GtkTextTag *tag = tagp->data;
|
2020-07-24 13:54:49 +00:00
|
|
|
|
int page = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (tag), "page"));
|
2003-08-05 19:16:01 +00:00
|
|
|
|
|
|
|
|
|
if (page != 0)
|
|
|
|
|
{
|
2020-09-17 02:31:34 +00:00
|
|
|
|
show_page (GTK_TEXT_VIEW (text_view), page);
|
2008-07-06 07:24:02 +00:00
|
|
|
|
break;
|
2003-08-05 19:16:01 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-02 03:55:47 +00:00
|
|
|
|
if (tags)
|
2003-08-05 19:16:01 +00:00
|
|
|
|
g_slist_free (tags);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Links can be activated by pressing Enter.
|
|
|
|
|
*/
|
|
|
|
|
static gboolean
|
2018-01-31 11:42:43 +00:00
|
|
|
|
key_pressed (GtkEventController *controller,
|
|
|
|
|
guint keyval,
|
|
|
|
|
guint keycode,
|
|
|
|
|
GdkModifierType modifiers,
|
|
|
|
|
GtkWidget *text_view)
|
2003-08-05 19:16:01 +00:00
|
|
|
|
{
|
|
|
|
|
GtkTextIter iter;
|
|
|
|
|
GtkTextBuffer *buffer;
|
2017-08-28 22:47:03 +00:00
|
|
|
|
|
|
|
|
|
switch (keyval)
|
2003-08-05 19:16:01 +00:00
|
|
|
|
{
|
2011-09-02 03:55:47 +00:00
|
|
|
|
case GDK_KEY_Return:
|
2010-09-08 17:35:51 +00:00
|
|
|
|
case GDK_KEY_KP_Enter:
|
2003-08-05 19:16:01 +00:00
|
|
|
|
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_view));
|
2011-09-02 03:55:47 +00:00
|
|
|
|
gtk_text_buffer_get_iter_at_mark (buffer, &iter,
|
2003-08-05 19:16:01 +00:00
|
|
|
|
gtk_text_buffer_get_insert (buffer));
|
|
|
|
|
follow_if_link (text_view, &iter);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-31 11:42:43 +00:00
|
|
|
|
return GDK_EVENT_PROPAGATE;
|
2003-08-05 19:16:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-01-16 04:24:50 +00:00
|
|
|
|
static void set_cursor_if_appropriate (GtkTextView *text_view,
|
2020-07-24 13:54:49 +00:00
|
|
|
|
int x,
|
|
|
|
|
int y);
|
2018-01-16 04:24:50 +00:00
|
|
|
|
|
2018-06-26 20:51:05 +00:00
|
|
|
|
static void
|
2019-05-29 17:10:46 +00:00
|
|
|
|
released_cb (GtkGestureClick *gesture,
|
|
|
|
|
guint n_press,
|
2020-07-24 20:32:16 +00:00
|
|
|
|
double x,
|
|
|
|
|
double y,
|
2019-05-29 17:10:46 +00:00
|
|
|
|
GtkWidget *text_view)
|
2003-08-05 19:16:01 +00:00
|
|
|
|
{
|
|
|
|
|
GtkTextIter start, end, iter;
|
|
|
|
|
GtkTextBuffer *buffer;
|
2018-06-26 20:51:05 +00:00
|
|
|
|
int tx, ty;
|
2017-08-28 22:47:03 +00:00
|
|
|
|
|
2018-06-26 20:51:05 +00:00
|
|
|
|
if (gtk_gesture_single_get_button (GTK_GESTURE_SINGLE (gesture)) > 1)
|
|
|
|
|
return;
|
2003-08-05 19:16:01 +00:00
|
|
|
|
|
2018-01-16 04:24:50 +00:00
|
|
|
|
gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (text_view),
|
|
|
|
|
GTK_TEXT_WINDOW_WIDGET,
|
2018-06-26 20:51:05 +00:00
|
|
|
|
x, y, &tx, &ty);
|
2003-08-05 19:16:01 +00:00
|
|
|
|
|
|
|
|
|
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_view));
|
|
|
|
|
|
|
|
|
|
/* we shouldn't follow a link if the user has selected something */
|
|
|
|
|
gtk_text_buffer_get_selection_bounds (buffer, &start, &end);
|
|
|
|
|
if (gtk_text_iter_get_offset (&start) != gtk_text_iter_get_offset (&end))
|
2018-06-26 20:51:05 +00:00
|
|
|
|
return;
|
2003-08-05 19:16:01 +00:00
|
|
|
|
|
2020-09-17 02:31:34 +00:00
|
|
|
|
if (gtk_text_view_get_iter_at_location (GTK_TEXT_VIEW (text_view), &iter, tx, ty))
|
2016-02-10 05:07:37 +00:00
|
|
|
|
follow_if_link (text_view, &iter);
|
2018-06-26 20:51:05 +00:00
|
|
|
|
}
|
2003-08-05 19:16:01 +00:00
|
|
|
|
|
2018-06-26 20:51:05 +00:00
|
|
|
|
static void
|
|
|
|
|
motion_cb (GtkEventControllerMotion *controller,
|
2020-07-24 20:32:16 +00:00
|
|
|
|
double x,
|
|
|
|
|
double y,
|
2018-06-26 20:51:05 +00:00
|
|
|
|
GtkTextView *text_view)
|
|
|
|
|
{
|
2020-09-17 02:31:34 +00:00
|
|
|
|
int tx, ty;
|
|
|
|
|
|
|
|
|
|
gtk_text_view_window_to_buffer_coords (text_view,
|
|
|
|
|
GTK_TEXT_WINDOW_WIDGET,
|
|
|
|
|
x, y, &tx, &ty);
|
|
|
|
|
|
|
|
|
|
set_cursor_if_appropriate (text_view, tx, ty);
|
2003-08-05 19:16:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2006-10-08 05:07:55 +00:00
|
|
|
|
static gboolean hovering_over_link = FALSE;
|
2003-08-05 19:16:01 +00:00
|
|
|
|
|
2011-09-02 03:55:47 +00:00
|
|
|
|
/* Looks at all tags covering the position (x, y) in the text view,
|
2003-08-05 19:16:01 +00:00
|
|
|
|
* and if one of them is a link, change the cursor to the "hands" cursor
|
|
|
|
|
* typically used by web browsers.
|
|
|
|
|
*/
|
|
|
|
|
static void
|
2020-09-17 02:31:34 +00:00
|
|
|
|
set_cursor_if_appropriate (GtkTextView *text_view,
|
|
|
|
|
int x,
|
|
|
|
|
int y)
|
2003-08-05 19:16:01 +00:00
|
|
|
|
{
|
|
|
|
|
GSList *tags = NULL, *tagp = NULL;
|
|
|
|
|
GtkTextIter iter;
|
|
|
|
|
gboolean hovering = FALSE;
|
|
|
|
|
|
2016-02-10 05:07:37 +00:00
|
|
|
|
if (gtk_text_view_get_iter_at_location (text_view, &iter, x, y))
|
2003-08-05 19:16:01 +00:00
|
|
|
|
{
|
2016-02-10 05:07:37 +00:00
|
|
|
|
tags = gtk_text_iter_get_tags (&iter);
|
|
|
|
|
for (tagp = tags; tagp != NULL; tagp = tagp->next)
|
2003-08-05 19:16:01 +00:00
|
|
|
|
{
|
2016-02-10 05:07:37 +00:00
|
|
|
|
GtkTextTag *tag = tagp->data;
|
2020-07-24 13:54:49 +00:00
|
|
|
|
int page = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (tag), "page"));
|
2016-02-10 05:07:37 +00:00
|
|
|
|
|
|
|
|
|
if (page != 0)
|
|
|
|
|
{
|
|
|
|
|
hovering = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2003-08-05 19:16:01 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (hovering != hovering_over_link)
|
|
|
|
|
{
|
|
|
|
|
hovering_over_link = hovering;
|
|
|
|
|
|
|
|
|
|
if (hovering_over_link)
|
2017-11-04 02:16:26 +00:00
|
|
|
|
gtk_widget_set_cursor_from_name (GTK_WIDGET (text_view), "pointer");
|
2003-08-05 19:16:01 +00:00
|
|
|
|
else
|
2017-11-04 02:16:26 +00:00
|
|
|
|
gtk_widget_set_cursor_from_name (GTK_WIDGET (text_view), "text");
|
2003-08-05 19:16:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2011-09-02 03:55:47 +00:00
|
|
|
|
if (tags)
|
2003-08-05 19:16:01 +00:00
|
|
|
|
g_slist_free (tags);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GtkWidget *
|
2003-11-08 22:08:05 +00:00
|
|
|
|
do_hypertext (GtkWidget *do_widget)
|
2003-08-05 19:16:01 +00:00
|
|
|
|
{
|
|
|
|
|
static GtkWidget *window = NULL;
|
|
|
|
|
|
|
|
|
|
if (!window)
|
|
|
|
|
{
|
|
|
|
|
GtkWidget *view;
|
|
|
|
|
GtkWidget *sw;
|
|
|
|
|
GtkTextBuffer *buffer;
|
2018-01-31 11:42:43 +00:00
|
|
|
|
GtkEventController *controller;
|
2003-08-05 19:16:01 +00:00
|
|
|
|
|
2020-02-14 19:55:36 +00:00
|
|
|
|
window = gtk_window_new ();
|
2015-06-28 13:23:28 +00:00
|
|
|
|
gtk_window_set_title (GTK_WINDOW (window), "Hypertext");
|
2017-10-31 06:41:15 +00:00
|
|
|
|
gtk_window_set_display (GTK_WINDOW (window),
|
|
|
|
|
gtk_widget_get_display (do_widget));
|
2020-09-17 02:31:34 +00:00
|
|
|
|
gtk_window_set_default_size (GTK_WINDOW (window), 330, 330);
|
|
|
|
|
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
|
2020-05-09 16:03:11 +00:00
|
|
|
|
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
|
2003-08-05 19:16:01 +00:00
|
|
|
|
|
|
|
|
|
view = gtk_text_view_new ();
|
|
|
|
|
gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (view), GTK_WRAP_WORD);
|
2020-09-17 02:31:34 +00:00
|
|
|
|
gtk_text_view_set_top_margin (GTK_TEXT_VIEW (view), 20);
|
|
|
|
|
gtk_text_view_set_bottom_margin (GTK_TEXT_VIEW (view), 20);
|
2016-02-10 05:07:37 +00:00
|
|
|
|
gtk_text_view_set_left_margin (GTK_TEXT_VIEW (view), 20);
|
|
|
|
|
gtk_text_view_set_right_margin (GTK_TEXT_VIEW (view), 20);
|
2020-09-17 02:31:34 +00:00
|
|
|
|
gtk_text_view_set_pixels_below_lines (GTK_TEXT_VIEW (view), 10);
|
2018-04-20 17:58:06 +00:00
|
|
|
|
controller = gtk_event_controller_key_new ();
|
2018-01-31 11:42:43 +00:00
|
|
|
|
g_signal_connect (controller, "key-pressed", G_CALLBACK (key_pressed), view);
|
2018-04-20 17:58:06 +00:00
|
|
|
|
gtk_widget_add_controller (view, controller);
|
2018-06-26 20:51:05 +00:00
|
|
|
|
|
2019-05-29 17:10:46 +00:00
|
|
|
|
controller = GTK_EVENT_CONTROLLER (gtk_gesture_click_new ());
|
2018-06-26 20:51:05 +00:00
|
|
|
|
g_signal_connect (controller, "released",
|
|
|
|
|
G_CALLBACK (released_cb), view);
|
|
|
|
|
gtk_widget_add_controller (view, controller);
|
|
|
|
|
|
|
|
|
|
controller = gtk_event_controller_motion_new ();
|
|
|
|
|
g_signal_connect (controller, "motion",
|
|
|
|
|
G_CALLBACK (motion_cb), view);
|
|
|
|
|
gtk_widget_add_controller (view, controller);
|
2003-08-05 19:16:01 +00:00
|
|
|
|
|
|
|
|
|
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
|
2019-11-01 18:30:33 +00:00
|
|
|
|
gtk_text_buffer_set_enable_undo (buffer, TRUE);
|
2011-09-02 03:55:47 +00:00
|
|
|
|
|
2020-06-24 15:25:09 +00:00
|
|
|
|
sw = gtk_scrolled_window_new ();
|
2003-08-05 19:16:01 +00:00
|
|
|
|
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
|
2008-07-06 07:24:02 +00:00
|
|
|
|
GTK_POLICY_AUTOMATIC,
|
|
|
|
|
GTK_POLICY_AUTOMATIC);
|
2020-05-02 21:26:54 +00:00
|
|
|
|
gtk_window_set_child (GTK_WINDOW (window), sw);
|
2020-05-02 04:51:20 +00:00
|
|
|
|
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), view);
|
2003-08-05 19:16:01 +00:00
|
|
|
|
|
2020-09-17 02:31:34 +00:00
|
|
|
|
show_page (GTK_TEXT_VIEW (view), 1);
|
2003-08-05 19:16:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2010-03-01 06:47:38 +00:00
|
|
|
|
if (!gtk_widget_get_visible (window))
|
2015-06-28 13:23:28 +00:00
|
|
|
|
gtk_widget_show (window);
|
2003-08-05 19:16:01 +00:00
|
|
|
|
else
|
2020-05-09 14:26:22 +00:00
|
|
|
|
gtk_window_destroy (GTK_WINDOW (window));
|
2003-08-05 19:16:01 +00:00
|
|
|
|
|
|
|
|
|
return window;
|
|
|
|
|
}
|