GtkTextView 文本着色未按预期工作

GtkTextView text coloring not working as expected

我正在尝试使用 GtkTextView 在代码中突出显示 C++ 样式的注释,但它似乎无法正常工作。我想创建一个函数,首先将所有突出显示重置为默认值(黑色),然后仅绘制与模式匹配的文本部分 /.?*/ 而正则表达式部分有效我Gtk 服从性有严重问题 - 它只是将文本涂黑并停止。这有什么合乎逻辑的解释吗?难道我做错了什么?我正在放置应该工作但没有工作的示例代码。编译命令为

gcc -o highlight_syntax_comments highlight_syntax_comments.c `pkg-config --cflags --libs gtk+-3.0`
#define GLIB_VERSION_2_28               (G_ENCODE_VERSION (2, 28))
#define GLIB_VERSION_MIN_REQUIRED       GLIB_VERSION_2_28

#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>

GtkTextBuffer *buffer;
GtkTextIter iter;

size_t f_size;
char* string;
int err;

static void highlight_syntax() {
  GtkTextIter match_start, match_end;
  GtkTextSearchFlags flags;
  
  GtkTextTagTable* table = gtk_text_buffer_get_tag_table (buffer);
  GtkTextTag* orange_tag   = gtk_text_tag_table_lookup (table, "orange");
  GtkTextTag* black_tag  = gtk_text_tag_table_lookup (table, "black");
  GtkTextTag* green_tag  = gtk_text_tag_table_lookup (table, "green");
  
  // reset color to black
  gtk_text_buffer_get_start_iter(GTK_TEXT_BUFFER (buffer), &match_start);
  gtk_text_buffer_get_end_iter(GTK_TEXT_BUFFER (buffer), &match_end);
  gtk_text_buffer_apply_tag (GTK_TEXT_BUFFER (buffer), black_tag,  &match_start, &match_end);

  // color first 100 chars
  gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER (buffer), &match_start, 0);
  gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER (buffer), &match_end, 100);
  gtk_text_buffer_apply_tag (GTK_TEXT_BUFFER (buffer), orange_tag,  &match_start, &match_end);

}

static gboolean key_callback(GtkWidget *widget,
                             GdkEventKey *event,
                             GtkIMContext *im_context) {
  highlight_syntax();
  return FALSE;
}

#include <stdio.h>
#include <stdlib.h>

#define FILE_OK 0
#define FILE_NOT_EXIST 1
#define FILE_TO_LARGE 2
#define FILE_READ_ERROR 3

char * c_read_file(const char * f_name, int * err, size_t* f_size) {
    char * buffer;
    size_t length;
    FILE * f = fopen(f_name, "rb");
    size_t read_length;

    if (f) {
        fseek(f, 0, SEEK_END);
        length = ftell(f);
        fseek(f, 0, SEEK_SET);

        buffer = (char *)malloc(length + 1);

        read_length = fread(buffer, 1, length, f);
        fclose(f);

        *err = FILE_OK;
        buffer[length] = '[=11=]';
        *f_size = length;
    }
    else {
        *err = FILE_NOT_EXIST;

        return NULL;
    }

    return buffer;
}

int main(int argc, gchar *argv[]) {

  GtkWidget *window;
  GtkWidget *view;
  GtkWidget *vbox;
  GtkWidget *scrolled_window; 

  gtk_init(&argc, &argv);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
  gtk_window_set_default_size(GTK_WINDOW(window), 800, 600);

  GtkIMContext *im_context = gtk_im_multicontext_new();
  GdkWindow *gdk_window = gtk_widget_get_window(GTK_WIDGET(window));
  gtk_im_context_set_client_window(im_context, gdk_window);
  gtk_im_context_focus_in(im_context);

  vbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
  view = gtk_text_view_new();
  gtk_widget_add_events(view, GDK_BUTTON_PRESS_MASK);
  gtk_box_pack_start(GTK_BOX(vbox), view, TRUE, TRUE, 0);

  scrolled_window = gtk_scrolled_window_new (NULL, NULL);
  gtk_container_add (GTK_CONTAINER (scrolled_window),
                    vbox);

  buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(view));
  gtk_text_buffer_get_iter_at_offset(buffer, &iter, 0);
  
  gtk_text_buffer_create_tag(buffer, "orange",  "foreground", "#e87d3e", NULL); 
  gtk_text_buffer_create_tag(buffer, "green", "foreground", "#A6E22E", NULL); 
  gtk_text_buffer_create_tag(buffer, "black", "foreground", "#000000", NULL); 

  string = c_read_file("./highlight_syntax_comments.c", &err, &f_size);
  gtk_text_buffer_insert(buffer, &iter, string, -1);

  highlight_syntax();

  gtk_container_add(GTK_CONTAINER(window), scrolled_window);

  g_signal_connect(G_OBJECT(window), "destroy",
        G_CALLBACK(gtk_main_quit), NULL);
  g_signal_connect(window, "key-press-event",
      G_CALLBACK(key_callback), im_context);

  gtk_widget_show_all(window);

  gtk_main();

  return 0;
}

gtk_text_tag_set_priority() 的文档对此进行了解释 — 设置一个标签不会删除另一个标签,因此橙色和黑色标签同时应用于文本。由于黑色标签是最后添加到标签 table 中的,它的优先级最高,因此它会覆盖橙色标签,即使您在应用黑色标签后在文本上应用了橙色标签。

解决方案是给予橙色标签更高的优先级,或者确保从要应用橙色标签的文本中删除黑色标签。