Reading help file into textview

Hi,
I’m using Gtk 3.2 on Ubuntu 18.04.1 LTS with C language. I have GtkMenuItem ‘Help’, with submenu ‘contents’, this calls ‘callback_contents()’ as shown below. The included comments describe the problems in reading a textfile into a textview buffer to create help documentation. The textfile was created in another part of the program using other menuitems ‘file/new’ ‘file/save’ as per modified versions of Andrew Krauses Gtk 2 book. It compiles with no warnings (other than a couple of unused variables) and when the submenuitem ‘help/contents’ is clicked the contents of the .txt file are displayed in the transient window as desired, but the runtime message:

(myexec:3474): Gtk-CRITICAL **: 19:26:32.147: gtk_text_buffer_emit_insert: assertion 'g_utf8_validate (text, len, NULL)' failed

is displayed at the terminal, once for each character in the file. How do I stop this? It seems to me that by writing and reading from the same system would mean that it would naturally be UTF8 coded. I have had previous version built with ui manager that included <?xml version="1.0" encoding="UTF-8"?> command at the start of the ui file, but the current version is fully coded.
Also included below are the help_file.txt contents as well as other failed and commented attempts in the callback_contents() function.

  void callback_contents(GtkMenuItem *contents, struct main_struct *stuff)
  {
  printf("Hello from callback_contents()\n");
    int i = 0;
    int count = 0;

    GtkWidget *window_help = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(window_help), "Help");
    gtk_container_set_border_width(GTK_CONTAINER(window_help), 5);
    gtk_window_set_default_size(GTK_WINDOW(window_help), 600, 250);
    gtk_window_set_position(GTK_WINDOW(window_help), GTK_WIN_POS_CENTER);
    gtk_window_set_resizable(GTK_WINDOW(window_help), TRUE);

    GtkTextBuffer *buffer_textview_help;
    GtkWidget *textview_help;
    GtkWidget *entry_help;

    textview_help = gtk_text_view_new();
    gtk_text_view_set_editable(GTK_TEXT_VIEW(textview_help), FALSE);
    gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(textview_help), TRUE);
    gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(textview_help), GTK_WRAP_WORD);
    gtk_text_view_set_pixels_above_lines(GTK_TEXT_VIEW(textview_help), 5);
    gtk_text_view_set_pixels_below_lines(GTK_TEXT_VIEW(textview_help), 5);
    gtk_text_view_set_pixels_inside_wrap(GTK_TEXT_VIEW(textview_help), 5);
    gtk_text_view_set_left_margin(GTK_TEXT_VIEW(textview_help), 10);
    gtk_text_view_set_right_margin(GTK_TEXT_VIEW(textview_help), 10);

    entry_help = gtk_entry_new();
    gtk_entry_set_text(GTK_ENTRY(entry_help), "Search for ...");

    buffer_textview_help = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview_help));

    // This works but I want to read it from file:
    /*gtk_text_buffer_set_text(buffer_textview_help,
 "Hello,\nhow\n are\n you? textview_help\n***********************\n\n\n\n\n\n\n** **\n\n\n\n\n\n\n** **\n\n\n\n\n\n\n** **\n\n\n\n\n\n\n** **\n\n\nroger1\n\n\n\n** **\n\n\nroger2\n\n\n\n** **\n\n\n\nroger3\n\n\n** **\n\n\n\nroger4\n\n\n** **\n\n\nroger5\n\n\n\n** **\n\n\n\nroger6\n\n\n** ****\n\n\n\nroger7\n\n\n** ***\n\n\n\nroger8\n\n\n** **\n\n\nroger9\n\n\n\n** **\n\n\n\nroger10\n\n\n** **\n\n\nroger11\n\n\n\n** **\nend\n", -1);*/

    char line[82];
    char string[303];

    // Compiles but get segmentation fault when run
    /*char help_contents;
    FILE* infile_help_contents = fopen("help_file.txt", "r");
    fscanf(infile_help_contents, "%s\n", &help_contents);
    gtk_text_buffer_set_text(buffer_textview_help, (char *) &help_contents, -1);
    fclose(infile_help_contents);*/


    FILE* infile_help_contents = fopen("help_file.txt", "r");

    // This works but only shows the first line (81 characters)
    /*fgets(string, 166, infile_help_contents);
    gtk_text_buffer_set_text(buffer_textview_help, (char *) string, -1);*/

    // This works but also only shows the first line (81 characters)
    /*fscanf(infile_help_contents, "%s\n", (char *) &string);
    gtk_text_buffer_set_text(buffer_textview_help, (char *) string, -1);*/

/*******************************************************************************************/
    // Here is the relevant bit:
    // This shows all in the file, but get this run-time message:
    // (myexec:3474): Gtk-CRITICAL **: 19:26:32.147: gtk_text_buffer_emit_insert:
    // assertion 'g_utf8_validate (text, len, NULL)' failed
    for (i=0; i<303; i++)
    {
    string[i] = fgetc(infile_help_contents);
    gtk_text_buffer_set_text(buffer_textview_help, (char *) string, -1);
    }
/*******************************************************************************************/

    // No messages, but shows last line only
    /*for (i=0; i<303; i++)
    {
    fgets(string, 303*sizeof(char *), infile_help_contents);
    gtk_text_buffer_set_text(buffer_textview_help, (char *) string, -1);
    }*/

    // Only shows the last line
    /*while (fgets(line, 82, infile_help_contents) != NULL)
    {
    fgets(line, 82, infile_help_contents);
    gtk_text_buffer_set_text(buffer_textview_help, (char *) line, -1);
    printf("%s\n", line);
    count = count +1;
    printf("count = %d\n", count);
    i++;
    }*/

    // Only shows part of last line
    /*while ((i = fgetc(infile_help_contents)) != EOF)
    {
      fgets(line, 82, infile_help_contents);
      gtk_text_buffer_set_text(buffer_textview_help, (char *) line, -1);
      printf("%s\n", line);

    count = count +1;

    printf("count = %d\n", count);
    i++;
    }*/

    fclose(infile_help_contents);

    GtkWidget *grid_help = gtk_grid_new();

    GtkWidget *swin_textview_help = gtk_scrolled_window_new(NULL, NULL);
    gtk_widget_set_size_request (swin_textview_help, 300, 200);
    gtk_widget_set_hexpand(swin_textview_help, TRUE);
    gtk_widget_set_vexpand(swin_textview_help, TRUE);

    gtk_container_add (GTK_CONTAINER (swin_textview_help), textview_help);

    gtk_grid_attach(GTK_GRID(grid_help), entry_help, 0, 0, 10, 1);
    gtk_grid_attach(GTK_GRID(grid_help), swin_textview_help, 0, 2, 10, 1);

    gtk_container_add (GTK_CONTAINER (window_help), grid_help);
    gtk_widget_show_all(window_help);
  }

The contents of file ‘help_file.txt’:

 help_file.txt line1 nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn81
 help_file.txt line2 nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn81
 help_file.txt line3 nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn81
line4
line5
line6
line7
line8
line9
line10
last line (11)

From the fscanf man page:

the next pointer must be a pointer to the initial element of a character array that is long enough to hold the input sequence and the terminating null byte

You are passing a pointer to a single char, which is only big enough to hold the terminating nul byte.

From the fgets man page:

Reading stops after an EOF or a newline.

You only see a single line because you only read a single line.

Mmh, that one’s a bit surprising. s “Matches a sequence of non-white-space characters”, so I would expect the output to be the first word rather than the first line.

On each iteration, you read one line and set the text buffer’s text to that line, until you get to the last line that sticks.

Same with the while loop.

Passing -1 as length parameter means that the string is expected to be \0-terminated, but you are passing the partially-read contents plus uninitialized (read: random) memory in each iteration.

The following should work:

for (i = 0; i < 303; i++)
    string[i] = fgetc(infile_help_contents);
string[i] = '\0';

gtk_text_buffer_set_text (buffer_textview_help, (char *) string, -1);

However I strongly recomment that you use glib or gio instead of stdio, as it reduces significantly the number of ways you can shoot yourself in the foot:

g_autofree char *contents = NULL;

if (g_file_get_contents ("help_file.txt", &contents, NULL, NULL))
  gtk_text_buffer_set_text (buffer_textview_help, contents, -1);

Hi Florian,
here is my solution, thanks for your help, the solution lay in the \0 as you suggested. Will have a look at:

g_autofree char *contents = NULL;

if (g_file_get_contents ("help_file.txt", &contents, NULL, NULL))
  gtk_text_buffer_set_text (buffer_textview_help, contents, -1);

also,
Cheers,
Roger

void callback_contents(GtkMenuItem *contents, struct main_struct *stuff)
  {
  printf("Hello from callback_contents()\n");
    int i = 0;
    int cha_count = 0;

    GtkWidget *window_help = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(window_help), "Help");
    gtk_container_set_border_width(GTK_CONTAINER(window_help), 5);
    gtk_window_set_default_size(GTK_WINDOW(window_help), 600, 250);
    gtk_window_set_position(GTK_WINDOW(window_help), GTK_WIN_POS_CENTER);
    gtk_window_set_resizable(GTK_WINDOW(window_help), TRUE);

    GtkTextBuffer *buffer_textview_help;
    GtkWidget *textview_help;
    GtkWidget *entry_help;

    textview_help = gtk_text_view_new();
    gtk_text_view_set_editable(GTK_TEXT_VIEW(textview_help), FALSE);
    gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(textview_help), TRUE);
    gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(textview_help), GTK_WRAP_WORD);
    gtk_text_view_set_pixels_above_lines(GTK_TEXT_VIEW(textview_help), 5);
    gtk_text_view_set_pixels_below_lines(GTK_TEXT_VIEW(textview_help), 5);
    gtk_text_view_set_pixels_inside_wrap(GTK_TEXT_VIEW(textview_help), 5);
    gtk_text_view_set_left_margin(GTK_TEXT_VIEW(textview_help), 10);
    gtk_text_view_set_right_margin(GTK_TEXT_VIEW(textview_help), 10);

    entry_help = gtk_entry_new();
    gtk_entry_set_text(GTK_ENTRY(entry_help), "Search for ...");
    GtkWidget *find_help = gtk_button_new_with_label("Find");
    g_signal_connect(G_OBJECT(find_help), "clicked", G_CALLBACK(search_help), stuff);

    buffer_textview_help = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview_help));

    stuff->findstring_help = 1;
    GtkAdjustment *findstring_help_adj=gtk_adjustment_new(stuff->findstring_help,
          1, 2001, 1, 1, 1);
    GtkWidget *findstring_help_label=gtk_label_new("FindString");
    GtkWidget *findstring_help_spin=gtk_spin_button_new(findstring_help_adj, 1, 0);
    g_signal_connect(findstring_help_spin, "value-changed",
    G_CALLBACK(findstring_help_spin_changed), stuff);
    g_signal_connect(findstring_help_spin, "scroll-event", G_CALLBACK(gtk_true), NULL);

    FILE* infile_help_contents0 = fopen("help_file.txt", "r");
    while ((i = fgetc(infile_help_contents0)) != EOF)
    {
    cha_count = cha_count + 1;
    i++;
    }
    printf("cha_count = %d\n", cha_count);
    fclose(infile_help_contents0);

    char *string = malloc(cha_count*sizeof(char));

    FILE* infile_help_contents = fopen("help_file.txt", "r");

    for (i=0; i<=cha_count-1; i++)
    {
      if (i <= cha_count-2)
      {
      string[i] = fgetc(infile_help_contents);
      }
      else if (i == cha_count-1)
      {
      string[i] = '\0';
      }
      else
      {
      break;
      }
    }
    gtk_text_buffer_set_text(buffer_textview_help, (char *) string, -1);

    fclose(infile_help_contents);

    stuff->entry_help = entry_help;
    stuff->textview_help = textview_help;
    stuff->findstring_help_label = findstring_help_label;
    stuff->findstring_help_spin = findstring_help_spin;

    GtkWidget *grid_help = gtk_grid_new();

    GtkWidget *swin_textview_help = gtk_scrolled_window_new(NULL, NULL);
    gtk_widget_set_size_request (swin_textview_help, 300, 200);
    gtk_widget_set_hexpand(swin_textview_help, TRUE);
    gtk_widget_set_vexpand(swin_textview_help, TRUE);

    gtk_container_add (GTK_CONTAINER (swin_textview_help), textview_help);

    gtk_grid_attach(GTK_GRID(grid_help), entry_help, 0, 0, 5, 1);
    gtk_grid_attach(GTK_GRID(grid_help), find_help, 6, 0, 1, 1);
    gtk_grid_attach(GTK_GRID(grid_help), stuff->findstring_help_label, 7, 0, 1, 1);
    gtk_grid_attach(GTK_GRID(grid_help), stuff->findstring_help_spin, 8, 0, 1, 1);

    gtk_grid_attach(GTK_GRID(grid_help), swin_textview_help, 0, 2, 10, 1);

    gtk_container_add (GTK_CONTAINER (window_help), grid_help);

    gtk_widget_show_all(window_help);

    free(string);
  }

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.