管理GtkTextBuffer中的文本,有两种方式可以被用来追踪缓存中的位置:GtkTextIter和GtkTextMark。GTK+提供了函数,这两种类型的对象可以互相转换。
文本迭代器用于代表缓存中两个两个字符间的位置。它们用于管理缓存中的文本。文本迭代器的一个问题是,当文本缓存被编辑时,它们自动变成非法值了。插入一些文字,从缓存中删除一些文字,文本迭代器都变成非法状态了,因为迭代器注定是分配在栈上、立即使用。
为了在一个变化中的文本缓存中追踪位置,GTK+提供了GtkTextMark对象。当维护管理缓存时,文本标记保持有效,而且会根据缓存的变动移动位置。通过gtk_text_buffer_get_iter_at_mark(),您可以获得一个指向文本标记的迭代器,配合标记可以完美地追踪文档中的某个位置。
void gtk_text_buffer_get_iter_at_mark (GtkTextBuffer *buffer,
GtkTextIter *iter,
GtkTextMark *mark);
文本标记好像是文本中不可见的光标,根据文本如何被编辑,它会改变位置。如果在标记之前添加了文本,它会向后移动,因此它保持在原文的位置。
默认状态下,文本标记有向右的重力作用。这个意思是说,如果插入了文本,它会向右移动。让我们假设,标记周围的文字被删除了。标记会在删除文本的两端之间
移动。那么,如果文本插入到原来标记所在区域,因为向右重力作用,标记会移动到新插入文字的右端。这有点像光标,因为插入了文字,光标保持在插入文本的右
边。
提示:默认状态下,文本标记在文本中不可见。通过调用gtk_text_mark_set_visible(),您可以让文本标记可见,它在标记的位置处放置了一个纵向短线。
有两种方式可以获得文本标记。您可以在指定的GtkTextIter位置处获得一个文本标记。还可以在通过一个名字字符串,建立一个文本标记,这让标记更容易追踪。
每个GtkTextBuffer都提供了两个默认的文本标记:insert和selection_bound。insert文本标记指的是缓存中当前的光
标位置。selection_bound文本标记指的是选择文本的边界,如果有选择文字的话。如果没有选择文字,这两个标记指向同一个位置。
当管理缓存的时候,insert和selection_bound文本标记十分有用。你可以操作他们自动选择或者取消选择缓存中的一段文字,而且你可以获得在缓存中文字插入的位置。
编辑文本缓存
GTK+提供了很多函数来获得文本迭代器以及管理文本缓存。在本节中,您将看到几个特别重要的方法,他们在Listing 7-4中用到,然后介绍一些更多的内容。Figure 7-3显示了一个程序,它能通过GtkTextBuffer插入和获得文字。
Listing 7-4是一个简单的例子,它有两个功能。如图7-4所示,当Insert
Text按钮被按下时,在GtkEntry构件中显示的字符串会被插入到当前光标位置。当按下Get
Text按钮时,选择的文本会被g_print()输出到屏幕。
Listing 7-4 使用文本迭代器(iterators.c)
#include
typedef struct
{
GtkWidget *entry, *textview;
} Widgets;
static void insert_text (GtkButton*, Widgets*);
static void retrieve_text (GtkButton*, Widgets*);
int main (int argc,
char *argv[])
{
GtkWidget *window, *scrolled_win, *hbox, *vbox, *insert, *retrieve;
Widgets *w = g_slice_new (Widgets);
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "Text Iterators");
gtk_container_set_border_width (GTK_CONTAINER (window), 10);
gtk_widget_set_size_request (window, -1, 200);
w->textview = gtk_text_view_new ();
w->entry = gtk_entry_new ();
insert = gtk_button_new_with_label ("Insert Text");
retrieve = gtk_button_new_with_label ("Get Text");
g_signal_connect (G_OBJECT (insert), "clicked",
G_CALLBACK (insert_text),
(gpointer) w);
g_signal_connect (G_OBJECT (retrieve), "clicked",
G_CALLBACK (retrieve_text),
(gpointer) w);
scrolled_win = gtk_scrolled_window_new (NULL, NULL);
gtk_container_add (GTK_CONTAINER (scrolled_win), w->textview);
hbox = gtk_hbox_new (FALSE, 5);
gtk_box_pack_start_defaults (GTK_BOX (hbox), w->entry);
gtk_box_pack_start_defaults (GTK_BOX (hbox), insert);
gtk_box_pack_start_defaults (GTK_BOX (hbox), retrieve);
vbox = gtk_vbox_new (FALSE, 5);
gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
gtk_container_add (GTK_CONTAINER (window), vbox);
gtk_widget_show_all (window);
gtk_main();
return 0;
}
/* Insert the text from the GtkEntry into the GtkTextView. */
static void
insert_text (GtkButton *button,
Widgets *w)
{
GtkTextBuffer *buffer;
GtkTextMark *mark;
GtkTextIter iter;
const gchar *text;
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (w->textview));
text = gtk_entry_get_text (GTK_ENTRY (w->entry));
mark = gtk_text_buffer_get_insert (buffer);
gtk_text_buffer_get_iter_at_mark (buffer, &iter, mark);
gtk_text_buffer_insert (buffer, &iter, text, -1);
}
/* Retrieve the selected text from the GtkTextView and display it
* to the user. */
static void
retrieve_text (GtkButton *button,
Widgets *w)
{
GtkTextBuffer *buffer;
GtkTextIter start, end;
gchar *text;
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (w->textview));
gtk_text_buffer_get_selection_bounds (buffer, &start, &end);
text = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
g_print ("%s\n", text);
}
在Listing 7-4中,您应该注意到,不象多数GTK+对象,文本迭代器被保存为非指针对象。这意味着它们在栈中直接分配出来。通过使用取地址符,迭代器的指针被传递给了函数。
迭代器的另外一个重要属性,在于一个迭代器可以被反复使用,因为每次编辑一个文本缓存时,迭代器就失效了。通过这种方式,您可以继续重用同一个GtkTextIter对象,而不是创建很多迭代器的变量。
获得文本迭代器和标记
正如前述,有许多函数可用于获得文本迭代器和标记,本章会使用它们中的很多方法。
Listing 7-4一开始就用gtk_text_buffer_get_insert()来获得insert标记。还可以使用gtk_text_buffer_get_selection_bound()来获得selection_bound标记。
mark = gtk_text_buffer_get_insert (buffer);
gtk_text_buffer_get_iter_at_mark (buffer, &iter, mark);
一旦您获得了一个标记,您可以通过gtk_text_buffer_get_iter_at_mark()把它翻译成文本迭代器,因此它可以用来管理文本缓存。
在Listing
7-4中,展示了另外一个函数gtk_text_buffer_get_selection_bounds()来获得文本迭代器,它返回在insert和
selection_bound标记位置处的文本迭代器。您可以设置一个或者两个文本迭代器参数为NULL,这样就阻止了参数的返回,如果您只需要一个返
回值,您就需要了解使用这个函数的这种方法。
当获得缓存中的内容时,您需要为文本片段指定开始和结束的文本迭代器。如果您想要获得文档的全部内容,您需要把迭代器指到文档开始和结束的位置,它可以用gtk_text_buffer_get_bounds()获得。
void gtk_text_buffer_get_bounds (GtkTextBuffer *buffer,
GtkTextIter *start,
GtkTextIter *end);
也可以通过gtk_text_buffer_get_start_iter()或者gtk_text_buffer_get_end_iter(),来分别获得文本缓存中开始和结束位置的迭代器。
缓存中的文本可以用gtk_text_buffer_get_text()来获得。他返回start和end之间的迭代器的所有文本。如果最后一个参数设置为TRUE,那么将只返回可见的文本。
gchar* gtk_text_buffer_get_text (GtkTextBuffer *buffer,
const GtkTextIter *start,
const GtkTextIter *end,
gboolean include_hidden_chars);
小心:只有获得缓存中的全部内容时,您才应该使用gtk_text_buffer_get_text()。它会忽略嵌入到文本缓存中的图像或者构件对象,因此字符索引未必正确对应正确地位置。为了获得文本缓存中的一部分,建议使用gtk_text_buffer_get_slice()。
回忆一下,偏移量指的是缓存中单个字符的数量。这些字符可能是一个或者多个字节长。gtk_text_buffer_get_iter_at_offset()函数可以用于获得一个迭代器,它从缓存开始位置计算指定偏移量。
void gtk_text_buffer_get_iter_at_offset (GtkTextBuffer *buffer,
GtkTextIter *iter,
gint character_offset);
GTK+还提供了gtk_text_buffer_get_iter_at_line_index(),它会选择某一行某一个字节的位置。使用这个函数的
时候您需要特别小心,因为索引一定要指向一个UTF-8字符的开始位置。一定要牢记UTF-8字符可能不止一个字节!
如果不用字符的字节偏移量来选择,您还可以通过gtk_text_buffer_get_iter_at_line()获得某一行的开始位置的迭代器。
void gtk_text_buffer_get_iter_at_line (GtkTextBuffer *buffer,
GtkTextIter *iter,
gint character_offset);
如果您想获得的迭代器,它指定的偏移量是从某一行开始字符计算的,您就可以使用gtk_text_buffer_get_iter_at_line_offset()。
改变文本缓存内容
您已经学到了如何重置文字缓存中的全部内容,但是更有用的是改变文档中的部分内容。为了实现这个目的,有许多函数可用。Listing 7-4显示了如何往缓存中插入一段文本。
如果您需要在缓存中的任意位置插入一段文本,您需要使用gtk_text_buffer_insert()。为了实现这个,您需要GtkTextIter
指向一个插入点,插入缓存的字符一定要UTF-8格式,还要一个文本长度。如果字符串是以NULL结尾的,您可以指定-1作为长度。
GtkTextMark* gtk_text_buffer_get_insert (GtkTextBuffer *buffer);
当调用了这个函数,文本缓存会发出insert-text信号,然后文本迭代器就失效了。然而,文本迭代器被重新初始化,指向插入文本的尾部。
一个更方便的函数,叫做gtk_text_buffer_insert_at_cursor(),可以用来在光标当前位置调用gtk_text_buffer_insert()。这个可以通过文本标记可以很容易地实现,但是它让您少调用几个函数。
void gtk_text_buffer_insert_at_cursor (GtkTextBuffer *buffer,
const gchar *text,
gint length);
通过gtk_text_buffer_delete(),您可以删除两个文本迭代器之间的文字。您可以随意指定两个迭代器的顺序,因为这个函数会自动把它们安放在争取的地方。
void gtk_text_buffer_delete (GtkTextBuffer *buffer,
GtkTextIter *start,
GtkTextIter *end);
这个函数会发出delete-range信号,然后两个迭代器都失效了。然而,开始和结束迭代器都被重新初始化,被放置在删除文本的位置。
剪切、拷贝和粘贴文本
当您右键点击一个GtkTextView构件时,会弹出一个右键菜单,包括几个选项。Figure 7-5展示了一个菜单的例子,尽管在您的系统中,菜单中的内容可能不尽相同。
三个选项非别是剪切、拷贝和粘贴,他们是多数文本编辑器的标准功能。它们被内置在每个GtkTextView构件中。然而,对于这些内置功能,有时候您需要实现您自己的版本,并且包含在程序的菜单和工具条之中。
Listing
7-5给了上述功能的例子。当三个GtkButton中的一个被点击,就会触发一个动作。试着使用这些按钮,还有右键菜单,来显示它们都使用同一个
GtkClipboard对象。这些函数都可以通过内置的快捷键被触发,他们分别是Ctrl+C、Ctrl+X和Ctrl+V。
Listing 7-5 使用剪切、拷贝和粘贴操作(cutcopypaste.c)
#include
static void cut_clicked (GtkButton*, GtkTextView*);
static void copy_clicked (GtkButton*, GtkTextView*);
static void paste_clicked (GtkButton*, GtkTextView*);
int main (int argc,
char *argv[])
{
GtkWidget *window, *scrolled_win, *textview, *cut, *copy, *paste, *hbox, *vbox;
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "Cut, Copy & Paste");
gtk_container_set_border_width (GTK_CONTAINER (window), 10);
textview = gtk_text_view_new ();
cut = gtk_button_new_from_stock (GTK_STOCK_CUT);
copy = gtk_button_new_from_stock (GTK_STOCK_COPY);
paste = gtk_button_new_from_stock (GTK_STOCK_PASTE);
g_signal_connect (G_OBJECT (cut), "clicked",
G_CALLBACK (cut_clicked),
(gpointer) textview);
g_signal_connect (G_OBJECT (copy), "clicked",
G_CALLBACK (copy_clicked),
(gpointer) textview);
g_signal_connect (G_OBJECT (paste), "clicked",
G_CALLBACK (paste_clicked),
(gpointer) textview);
scrolled_win = gtk_scrolled_window_new (NULL, NULL);
gtk_widget_set_size_request (scrolled_win, 300, 200);
gtk_container_add (GTK_CONTAINER (scrolled_win), textview);
hbox = gtk_hbox_new (TRUE, 5);
gtk_box_pack_start (GTK_BOX (hbox), cut, TRUE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (hbox), copy, TRUE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (hbox), paste, TRUE, TRUE, 0);
vbox = gtk_vbox_new (FALSE, 5);
gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
gtk_container_add (GTK_CONTAINER (window), vbox);
gtk_widget_show_all (window);
gtk_main();
return 0;
}
/* Copy the selected text to the clipboard and remove it from the buffer. */
static void
cut_clicked (GtkButton *cut,
GtkTextView *textview)
{
GtkClipboard *clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
GtkTextBuffer *buffer = gtk_text_view_get_buffer (textview);
gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
}
/* Copy the selected text to the clipboard. */
static void
copy_clicked (GtkButton *copy,
GtkTextView *textview)
{
GtkClipboard *clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
GtkTextBuffer *buffer = gtk_text_view_get_buffer (textview);
gtk_text_buffer_copy_clipboard (buffer, clipboard);
}
/* Insert the text from the clipboard into the text buffer. */
static void
paste_clicked (GtkButton *paste,
GtkTextView *textview)
{
GtkClipboard *clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
GtkTextBuffer *buffer = gtk_text_view_get_buffer (textview);
gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
}
GtkClipboard是一个关键的类,它为不同程序之间的数据交换提供了一种简单方式。为了获得已经创建好的剪贴板,请使用gtk_clipboard_get()。既然已经提供了默认的剪贴板,本书不再讲述如何创建您自己的剪贴板对象。
注意:虽然可以创建您自己的GtkClipboard对象,当执行基本任务的时候,您应该使用默认剪贴板。您可以给gtk_clipboard_get()传递GDK_SELECTION_CLIPBOARD参数来获得它。
可以很容易地和您创建的GtkClipboard对象进行直接交互,从中添加和删除数据。然而,当执行简单的操作,包括拷贝、从GtkTextView构件中获得字符串的时候,使用GtkTextbuffer提供的内置函数更有意义。
GtkTextBuffer三个剪贴板动作里面,拷贝文本是最简单的,它可以这样完成:
void gtk_text_buffer_copy_clipboard (GtkTextBuffer *buffer,
GtkClipboard *clipboard);
第二个剪贴板函数,gtk_text_buffer_cut_clipboard(),拷贝选择的文字到剪贴板中,并且把它从缓存中删除。如果选择的文本
没有设置可编辑标志,它会设置为函数第三个参数里的值。这个函数不仅拷贝文本,而且拷贝嵌入的对象,比如图像和文本标记。
void gtk_text_buffer_cut_clipboard (GtkTextBuffer *buffer,
GtkClipboard *clipboard,
gboolean default_editable);
最后一个剪贴板函数,gtk_text_buffer_paste_clipboard()首先获得剪贴板的内容。接着,这个函数会做两件事情中的一个。
如果第三个参数,它接受一个GtkTextIter,被指定了合法的值,它的内容就会被插入到迭代器指向的那个位置。如果第三个参数指定为NULL,内容
就会被插入到光标所在的位置。
void gtk_text_buffer_paste_clipboard (GtkTextBuffer *buffer,
GtkClipboard *clipboard,
GtkTextIter *override_location,
gboolean default_editable);
如果需要粘贴的部分内容没有设置可编辑状态,它会自动使用defalut_editable。在大部分情况下,您要设置这个参数为TRUE,因为它会允许粘贴的内容可编辑。您应该知道粘贴操作时异步完成的。
在文本缓存中查找
在多数使用GtkTextView构件的应用程序中,您经常需要在文本缓存中查找。GTK+提供了两个函数来再缓存中查找文
本:gtk_text_iter_forward_search()和gtk_text_iter_backward_search()。
下面的例子展示了如何使用第一个函数,在GtkTextBuffer中查找一个字符串;Figure 7-6显示了例子的一个屏幕截图。当用户点击了GTK_STOCK_FIND按钮,这个例子开始工作。
在Listing 7-6显示的例子,在文本缓存中搜索所有指定字符串的实例。一个对话框展示给用户,显示字符串在文档中出现的次数。
Listing 7-6 使用GtkTextIter搜索函数(find.c)
#include
typedef struct
{
GtkWidget *entry, *textview;
} Widgets;
static void search (GtkButton*, Widgets*);
int main (int argc,
char *argv[])
{
GtkWidget *window, *scrolled_win, *vbox, *hbox, *find;
Widgets *w = g_slice_new (Widgets);
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "Searching Buffers");
gtk_container_set_border_width (GTK_CONTAINER (window), 10);
w->textview = gtk_text_view_new ();
w->entry = gtk_entry_new ();
gtk_entry_set_text (GTK_ENTRY (w->entry), "Search for ...");
find = gtk_button_new_from_stock (GTK_STOCK_FIND);
g_signal_connect (G_OBJECT (find), "clicked",
G_CALLBACK (search),
(gpointer) w);
scrolled_win = gtk_scrolled_window_new (NULL, NULL);
gtk_widget_set_size_request (scrolled_win, 250, 200);
gtk_container_add (GTK_CONTAINER (scrolled_win), w->textview);
hbox = gtk_hbox_new (FALSE, 5);
gtk_box_pack_start (GTK_BOX (hbox), w->entry, TRUE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (hbox), find, FALSE, TRUE, 0);
vbox = gtk_vbox_new (FALSE, 5);
gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
gtk_container_add (GTK_CONTAINER (window), vbox);
gtk_widget_show_all (window);
gtk_main();
return 0;
}
/* Search for the entered string within the GtkTextView. Then tell the user
* how many times it was found. */
static void
search (GtkButton *button,
Widgets *w)
{
const gchar *find;
gchar *output;
GtkWidget *dialog;
GtkTextBuffer *buffer;
GtkTextIter start, begin, end;
gboolean success;
gint i = 0;
find = gtk_entry_get_text (GTK_ENTRY (w->entry));
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (w->textview));
gtk_text_buffer_get_start_iter (buffer, &start);
success = gtk_text_iter_forward_search (&start, (gchar*) find, 0,
&begin, &end, NULL);
while (success)
{
gtk_text_iter_forward_char (&start);
success = gtk_text_iter_forward_search (&start, (gchar*) find, 0,
&begin, &end, NULL);
start = begin;
i++;
}
output = g_strdup_printf ("The string '%s' was found %i times!", find, i);
dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_INFO,
GTK_BUTTONS_OK, output, NULL);
gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (dialog);
g_free (output);
}
搜索函数首先需要做的事就是通过gtk_text_buffer_get_start_iter()获得文档的下边界。我们不需要缓存中的边界位置,因为通过不设置搜索边界,它会自动设置文档的结束位置作为搜索的结束位置。
在缓存中向前搜索,通过gtk_text_iter_forward_search()实现的,返回TRUE表示找到了文本。否则,函数就会返回FALSE。
success = gtk_text_iter_forward_search (&start, find, 0, &begin, &end, NULL);
开始的时候您您必须指定开始迭代器的位置。只有在该位置后面的文本才会被搜索。下一步,您指定被搜索的文本。第三个参数允许您指定GtkTextSearchFlags枚举值,如果有必要;这个枚举值是下列组合:
. GTK_TEXT_SEARCH_VISIBLE_ONLY:不搜索缓存中的隐藏元素。
. GTK_TEXT_SEARCH_TEXT_ONLY:在搜索过程中忽略图像、衍生构件或者其它任何非文本对象。
如果您没有指定GTK_TEXT_SEARCH_TEXT_ONLY标志,您需要使用一个特殊的0xFFFC字符来代表衍生构件和嵌入的图片。匹配必须是
精确地,因此使用忽略非文本元素的标志是明智的。默认状态下,搜索是区分大小写,但是将来会介绍一个标志它支持不区分大小写的搜索。
下面两个迭代器用于指明开始和结束位置,如果发现了一个结果。如果您不想追踪结果的位置,您可以为这两个迭代器指定为NULL。
最后一个参数允许您指定一个搜索的边界迭代器。这个函数智慧搜索最多有限个匹配的结果。如果您的程序需要处理巨大的缓存,有限制的搜索是个好主意。否则,您要承担锁住屏幕的风险,直到搜索结束。如果您想一直搜索到缓存结尾,使用NULL作为边界迭代器。
用gtk_text_iter_backward_search()搜索和gtk_text_iter_forward_search()类似,出来
limit必须放置在start_pos之前。如果您没有设置一个限制迭代器,这个函数会假设它一直搜索到缓存的开始位置。您需要小心处理这个,因为反复
搜索整个缓存,或者搜索一个很大的缓存,都是费时的。
gboolean gtk_text_iter_backward_search (const GtkTextIter *start_pos,
const gchar *text_string,
GtkTextSearchFlags flags,
GtkTextIter *match_start,
GtkTextIter *match_end,
const GtkTextIter *limit);
在多数程序中,您会标记上搜索的结果,比如选择它。 您可以使用gtk_text_buffer_select_range()来完成这个。这个函数会同时移动insert和selection_bound标记,到两个迭代器参数指定的位置。
void gtk_text_buffer_select_range (GtkTextBuffer *buffer,
const GtkTextIter *ins,
const GtkTextIter *sel_bound);
如果您收工分成两步来移动标记,这回导致屏幕显示混乱,因为文本被选择了多次。这个函数消除了这个困惑,它只用一次就重新设置了选择区域。
滚动文本缓存
GTK+不会滚动到您选择的搜索结果处。为了实现这个,您首先需要调用gtk_text_buffer_create_mark(),在发现文本的地方创建一个临时的GtkTextMark。
GtkTextMark* gtk_text_buffer_create_mark (GtkTextBuffer *buffer,
const gchar *name,
const GtkTextIter *location,
gboolean left_gravity);
gtk_text_buffer_create_mark()的第二个参数允许您指定一个字符串,作为标记的名字。在后面会提到,不需要真正的标记对
象,通过这个名字就可以饮用标记。这个标记被创建在指定的文本迭代器的位置。如果重力效果向左,设置最后一个参数为TRUE。
然后,使用gtk_text_view_scroll_mark_onscreen()来滚动缓存,这样标记就显示在屏幕上了。当您使用完了这个标记,您可以从缓存中删除它,通过调用函数gtk_text_buffer_delete_mark()。
void gtk_text_view_scroll_mark_onscreen (GtkTextView *textview,
GtkTextMark *mark);
使用gtk_text_view_scroll_mark_onscreen()的问题是,它只滚动在屏幕上显示出标记的最小距离。举例来说,您也许想要
让标记位于缓存的中间。为了指定在可见缓存的什么位置显示标记,您可以调用gtk_text_view_scroll_to_mark()指定对齐参数。
void gtk_text_view_scroll_to_mark (GtkTextView *textview,
GtkTextMark *mark,
gdouble margin,
gboolean use_align,
gdouble xalign,
gdouble yalign);
开始您要放置一个边距,它会缩小可滚动区域。边距必须被指定为浮点数,根据这个参数来减少区域。在多数情况下,您会把边距设置为0.0,因此区域根本不会被缩小。
如果您指定use_align参数为FALSE,这个函数会滚动一个最小的距离,让标记显示在屏幕上。否则,这个函数会使用两个对齐参数作为参照,这允许您在可见区域内指定标记的水平和垂直对齐参数。
参数0.0的对齐方式,表示在可见区域的左边或者上边,1.0指的是右边或者下面,0.5指的是中间。这个函数会尽量滚动到位,但是它也可能无法滚动到指定位置。举例来说,滚动到缓存的最上面一行了,但是需要滚动的缓存还比一行还高。
还有另外一个函数,gtk_text_view_scroll_to_iter(),它和gtk_text_view_scroll_to_mark()
有相同的行为。唯一的区别是,它接受GtkTextIter而不是GtkTextMark标记位置,尽管在多数情况下,您应该使用文本标记。