Chinaunix首页 | 论坛 | 博客
  • 博客访问: 74984
  • 博文数量: 34
  • 博客积分: 82
  • 博客等级: 民兵
  • 技术积分: 180
  • 用 户 组: 普通用户
  • 注册时间: 2012-02-23 18:51
文章分类
文章存档

2013年(2)

2012年(33)

分类:

2012-12-11 11:08:34

原文地址:7.3 文本迭代器和标记 作者:kongkong011

2012-07-29 00:12:45|  分类: GTK |  标签:gtk+  编程基础   |字号 

        管理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插入和获得文字。

7.3 文本迭代器和标记 - 郭映辉 - 郭映辉
 
        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展示了一个菜单的例子,尽管在您的系统中,菜单中的内容可能不尽相同。

7.3 文本迭代器和标记 - 郭映辉 - 郭映辉
 
        三个选项非别是剪切、拷贝和粘贴,他们是多数文本编辑器的标准功能。它们被内置在每个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按钮,这个例子开始工作。

7.3 文本迭代器和标记 - 郭映辉 - 郭映辉
 
        在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标记位置,尽管在多数情况下,您应该使用文本标记。
阅读(1296) | 评论(0) | 转发(0) |
0

上一篇:多线程并发

下一篇:getsockname与getpeername

给主人留下些什么吧!~~