示例#1
0
文件: gtkspell.c 项目: jmissig/gabber
static void
check_range(GtkSpell *spell, GtkTextBuffer *buffer,
            GtkTextIter start, GtkTextIter end) {
	/* we need to "split" on word boundaries.
	 * luckily, pango knows what "words" are 
	 * so we don't have to figure it out. */

	GtkTextIter wstart, wend;
	if (debug) {
		g_print("check_range: "); print_iter("s", &start); print_iter("e", &end); g_print(" -> ");
	}

	if (gtk_text_iter_inside_word(&end))
		gtk_text_iter_forward_word_end(&end);
	if (!gtk_text_iter_starts_word(&start)) {
		if (gtk_text_iter_inside_word(&start) || 
				gtk_text_iter_ends_word(&start)) {
			gtk_text_iter_backward_word_start(&start);
		} else {
			/* if we're neither at the beginning nor inside a word,
			 * me must be in some spaces.
			 * skip forward to the beginning of the next word. */
			//gtk_text_buffer_remove_tag(buffer, tag_highlight, &start, &end);
			if (gtk_text_iter_forward_word_end(&start))
				gtk_text_iter_backward_word_start(&start);
		}
	}
	gtk_text_buffer_remove_tag(buffer, spell->tag_highlight, &start, &end);

	if (debug) {print_iter("s", &start); print_iter("e", &end); g_print("\n");}

	wstart = start;
	while (gtk_text_iter_compare(&wstart, &end) < 0) {
		/* move wend to the end of the current word. */
		wend = wstart;
		gtk_text_iter_forward_word_end(&wend);

		check_word(spell, buffer, &wstart, &wend);

		/* now move wend to the beginning of the next word, */
		gtk_text_iter_forward_word_end(&wend);
		gtk_text_iter_backward_word_start(&wend);
		/* make sure we've actually advanced
		 * (we don't advance in some corner cases), */
		if (gtk_text_iter_equal(&wstart, &wend))
			break; /* we're done in these cases.. */
		/* and then pick this as the new next word beginning. */
		wstart = wend;
	}
}
示例#2
0
文件: extra.c 项目: agaX/SpellChecker
/**
  Kolorowanie słów.
  Słowa nie znajdujące się w słowniku - potencjalnie błędne - zostają
  oznaczone na czerwono.
  */
static void show_errors() {
  GtkTextIter start, end, text_end;
  int i, range;
  char *word;
  gunichar *wword;

  gtk_text_buffer_create_tag(editor_buf, "red_fg", 
                             "foreground", "red", 
                             "weight", PANGO_WEIGHT_BOLD, NULL);
  gtk_text_buffer_get_end_iter(editor_buf, &text_end);
  gtk_text_buffer_get_start_iter(editor_buf, &end);
  range = gtk_text_buffer_get_char_count(editor_buf);
  while (!gtk_text_iter_is_end(&end)) {
    gtk_text_iter_forward_word_end(&end); 
    start = end;
    gtk_text_iter_backward_word_start(&start); 

    word = gtk_text_iter_get_text(&start, &end);
    wword = g_utf8_to_ucs4_fast(word, -1, NULL);
    if (make_lowercase(wword)) {
      if (!dictionary_find(dict, wword))
      gtk_text_buffer_apply_tag_by_name(editor_buf, "red_fg", 
                                      &start, &end);
    }
    g_free(word);
    g_free(wword);
  }

}
示例#3
0
static void
update_words (ExampleAppWindow *win)
{
  ExampleAppWindowPrivate *priv;
  GHashTable *strings;
  GHashTableIter iter;
  GtkWidget *tab, *view, *row;
  GtkTextBuffer *buffer;
  GtkTextIter start, end;
  GList *children, *l;
  gchar *word, *key;

  priv = example_app_window_get_instance_private (win);

  tab = gtk_stack_get_visible_child (GTK_STACK (priv->stack));

  if (tab == NULL)
    return;

  view = gtk_bin_get_child (GTK_BIN (tab));
  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));

  strings = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);

  gtk_text_buffer_get_start_iter (buffer, &start);
  while (!gtk_text_iter_is_end (&start))
    {
      while (!gtk_text_iter_starts_word (&start))
        {
          if (!gtk_text_iter_forward_char (&start))
            goto done;
        }
      end = start;
      if (!gtk_text_iter_forward_word_end (&end))
        goto done;
      word = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
      g_hash_table_add (strings, g_utf8_strdown (word, -1));
      g_free (word);
      start = end;
    }

done:
  children = gtk_container_get_children (GTK_CONTAINER (priv->words));
  for (l = children; l; l = l->next)
    gtk_container_remove (GTK_CONTAINER (priv->words), GTK_WIDGET (l->data));
  g_list_free (children);

  g_hash_table_iter_init (&iter, strings);
  while (g_hash_table_iter_next (&iter, (gpointer *)&key, NULL))
    {
      row = gtk_button_new_with_label (key);
      g_signal_connect (row, "clicked",
                        G_CALLBACK (find_word), win);
      gtk_widget_show (row);
      gtk_container_add (GTK_CONTAINER (priv->words), row);
    }

  g_hash_table_unref (strings);
}
示例#4
0
文件: gtkspell.c 项目: jmissig/gabber
static void
get_cur_word_extents(GtkTextBuffer *buffer,
                     GtkTextIter *start, GtkTextIter *end) {
	gtk_text_buffer_get_iter_at_mark(buffer, start, 
			gtk_text_buffer_get_insert(buffer));
	if (!gtk_text_iter_starts_word(start)) 
		gtk_text_iter_backward_word_start(start);
	*end = *start;
	if (gtk_text_iter_inside_word(end))
		gtk_text_iter_forward_word_end(end);
}
示例#5
0
// Koloruje słowa nie ze słownika na czerwono
static void ColorMistakes (GtkMenuItem *item, gpointer data) {
  GtkTextIter start, end, buffEnd;

  gtk_text_buffer_get_start_iter(editor_buf, &end);

  //Teraz sztuczką przesuwamy końcowy iterator na koniec ostatniego słowa
  gtk_text_buffer_get_end_iter(editor_buf, &buffEnd);
  gtk_text_iter_backward_word_start(&buffEnd);
  gtk_text_iter_forward_word_end(&buffEnd);

  gtk_text_buffer_create_tag(editor_buf, "red_fg", 
                             "foreground", "red", 
                             "weight", PANGO_WEIGHT_BOLD, NULL);

  // Aktualizacja słownika
  if(update_actual_dict() < 0)
    return;
  start = end;

  while (!gtk_text_iter_equal(&end, &buffEnd)) {
    // Inkrementacja zmiennych
		gtk_text_iter_forward_word_end(&end); 
		start = end;
		gtk_text_iter_backward_word_start(&start);

    // Usuwamy etykietkę ze słowa jeśli jest
    gtk_text_buffer_remove_tag_by_name(editor_buf, "red_fg", 
                                      &start, &end);

    // Separujemy słowo
    char* word = gtk_text_iter_get_text(&start, &end);
    gunichar* wword = g_utf8_to_ucs4_fast(word, -1, NULL);

    // Jeśli znaleziono w słowniku to kolorujemy
    if(!dictionary_find(dict, (const wchar_t*)wword))
      gtk_text_buffer_apply_tag_by_name(editor_buf, "red_fg", 
                                        &start, &end);
    g_free(word);

  }
}
示例#6
0
static void
update_current (GeditDocument *doc,
		gint           current)
{
	CheckRange *range;
	GtkTextIter iter;
	GtkTextIter end_iter;

	gedit_debug (DEBUG_PLUGINS);

	g_return_if_fail (doc != NULL);
	g_return_if_fail (current >= 0);

	range = get_check_range (doc);
	g_return_if_fail (range != NULL);

	gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (doc), 
					    &iter, current);

	if (!gtk_text_iter_inside_word (&iter))
	{	
		/* if we're not inside a word,
		 * we must be in some spaces.
		 * skip forward to the beginning of the next word. */
		if (!gtk_text_iter_is_end (&iter))
		{
			gtk_text_iter_forward_word_end (&iter);
			gtk_text_iter_backward_word_start (&iter);	
		}
	}
	else
	{
		if (!gtk_text_iter_starts_word (&iter))
			gtk_text_iter_backward_word_start (&iter);	
	}

	gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (doc),
					  &end_iter,
					  range->end_mark);

	if (gtk_text_iter_compare (&end_iter, &iter) < 0)
	{	
		gtk_text_buffer_move_mark (GTK_TEXT_BUFFER (doc),
					   range->current_mark,
					   &end_iter);
	}
	else
	{
		gtk_text_buffer_move_mark (GTK_TEXT_BUFFER (doc),
					   range->current_mark,
					   &iter);
	}
}
示例#7
0
文件: gtkspell.c 项目: jmissig/gabber
static gboolean
gtkspell_text_iter_forward_word_end(GtkTextIter *i) {
	GtkTextIter iter;

/* heuristic: 
 * if we're on an singlequote/apostrophe and
 * if the next letter is alphanumeric,
 * this is an apostrophe. */

	if (!gtk_text_iter_forward_word_end(i))
		return FALSE;

	if (gtk_text_iter_get_char(i) != '\'')
		return TRUE;

	iter = *i;
	if (gtk_text_iter_forward_char(&iter)) {
		if (g_unichar_isalpha(gtk_text_iter_get_char(&iter))) {
			return (gtk_text_iter_forward_word_end(i));
		}
	}

	return TRUE;
}
static void
get_word_extents_from_mark (GtkTextBuffer *buffer,
			    GtkTextIter   *start,
			    GtkTextIter   *end,
			    GtkTextMark   *mark)
{
	gtk_text_buffer_get_iter_at_mark(buffer, start, mark);

	if (!gtk_text_iter_starts_word (start))
		gtk_text_iter_backward_word_start (start);

	*end = *start;

	if (gtk_text_iter_inside_word (end))
		gtk_text_iter_forward_word_end (end);
}
示例#9
0
static gchar *
get_current_word (GeditDocument *doc, gint *start, gint *end)
{
	const CheckRange *range;
	GtkTextIter end_iter;
	GtkTextIter current_iter;
	gint range_end;

	gedit_debug (DEBUG_PLUGINS);

	g_return_val_if_fail (doc != NULL, NULL);
	g_return_val_if_fail (start != NULL, NULL);
	g_return_val_if_fail (end != NULL, NULL);

	range = get_check_range (doc);
	g_return_val_if_fail (range != NULL, NULL);

	gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (doc), 
			&end_iter, range->end_mark);

	range_end = gtk_text_iter_get_offset (&end_iter);

	gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (doc), 
			&current_iter, range->current_mark);

	end_iter = current_iter;

	if (!gtk_text_iter_is_end (&end_iter))
	{
		gedit_debug_message (DEBUG_PLUGINS, "Current is not end");

		gtk_text_iter_forward_word_end (&end_iter);
	}

	*start = gtk_text_iter_get_offset (&current_iter);
	*end = MIN (gtk_text_iter_get_offset (&end_iter), range_end);

	gedit_debug_message (DEBUG_PLUGINS, "Current word extends [%d, %d]", *start, *end);

	if (!(*start < *end))
		return NULL;

	return gtk_text_buffer_get_slice (GTK_TEXT_BUFFER (doc),
					  &current_iter,
					  &end_iter,
					  TRUE);
}
示例#10
0
gboolean
ide_editor_spell_utils_text_iter_forward_word_end (GtkTextIter *iter)
{
  g_return_val_if_fail (iter != NULL, FALSE);

  while (gtk_text_iter_forward_word_end (iter))
    {
      GtkTextIter next_char;

      if (!is__text_iter_apostrophe_or_dash (iter))
        return TRUE;

      next_char = *iter;
      gtk_text_iter_forward_char (&next_char);
      if (!gtk_text_iter_starts_word (&next_char))
        return TRUE;

      *iter = next_char;
    }

  return FALSE;
}
示例#11
0
文件: console.c 项目: aylusltd/gretl
static gint console_complete_word (GtkTextBuffer *buf,
				   GtkTextIter *iter)
{
    GtkTextIter start, end;
    const char *targ = NULL;
    gchar *src;

    start = end = *iter;

    if (!gtk_text_iter_starts_word(&start)) {
	gtk_text_iter_backward_word_start(&start);
    }

    if (!gtk_text_iter_ends_word(&end)) {
	gtk_text_iter_forward_word_end(&end);
    }

    src = gtk_text_buffer_get_text(buf, &start, &end, FALSE);

    if (src != NULL && *src != '\0') {
	if (gtk_text_iter_get_line_offset(&start) == 2) {
	    /* first word on line */
	    targ = gretl_command_complete(src);
	} else {
	    targ = console_varname_complete(src);
	}
	if (targ != NULL) {
	    gtk_text_buffer_delete(buf, &start, &end);
	    gtk_text_buffer_insert(buf, &start, targ, -1);
	} else {
	    console_beep();
	}
    } 

    g_free(src);

    return TRUE;
}
示例#12
0
ParseWords::ParseWords(const ustring & text)
// Parses a line of text in its separate words.
// Note: This is comparable to object Parse, but does a better job.
{
  // Load text into buffer.
  ustring text2(text);
  text2.append(" ");
  GtkTextBuffer *textbuffer;
  textbuffer = gtk_text_buffer_new(NULL);
  gtk_text_buffer_set_text(textbuffer, text2.c_str(), -1);
  // Iterators.  
  GtkTextIter startiter, enditer;
  // Parse into separate words.
  gtk_text_buffer_get_start_iter(textbuffer, &enditer);
  while (gtk_text_iter_forward_word_end(&enditer)) {
    startiter = enditer;
    gtk_text_iter_backward_word_start(&startiter);
    ustring word = gtk_text_iter_get_text(&startiter, &enditer);
    words.push_back(word);
  }
  // Free memory
  g_object_unref(textbuffer);
}
示例#13
0
gboolean
xed_spell_utils_skip_no_spell_check (GtkTextIter *start,
                                       GtkTextIter *end)
{
	GtkSourceBuffer *buffer = GTK_SOURCE_BUFFER (gtk_text_iter_get_buffer (start));

	while (gtk_source_buffer_iter_has_context_class (buffer, start, "no-spell-check"))
	{
		GtkTextIter last = *start;

		if (!gtk_source_buffer_iter_forward_to_context_class_toggle (buffer, start, "no-spell-check"))
		{
			return FALSE;
		}

		if (gtk_text_iter_compare (start, &last) <= 0)
		{
			return FALSE;
		}

		gtk_text_iter_forward_word_end (start);
		gtk_text_iter_backward_word_start (start);

		if (gtk_text_iter_compare (start, &last) <= 0)
		{
			return FALSE;
		}

		if (gtk_text_iter_compare (start, end) >= 0)
		{
			return FALSE;
		}
	}

	return TRUE;
}
示例#14
0
static void
set_check_range (GeditDocument *doc,
		 GtkTextIter   *start,
		 GtkTextIter   *end)
{
	CheckRange *range;
	GtkTextIter iter;

	gedit_debug (DEBUG_PLUGINS);

	range = get_check_range (doc);

	if (range == NULL)
	{
		gedit_debug_message (DEBUG_PLUGINS, "There was not a previous check range");

		gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (doc), &iter);

		range = g_new0 (CheckRange, 1);

		range->start_mark = gtk_text_buffer_create_mark (GTK_TEXT_BUFFER (doc),
				"check_range_start_mark", &iter, TRUE);

		range->end_mark = gtk_text_buffer_create_mark (GTK_TEXT_BUFFER (doc),
				"check_range_end_mark", &iter, FALSE);

		range->current_mark = gtk_text_buffer_create_mark (GTK_TEXT_BUFFER (doc),
				"check_range_current_mark", &iter, TRUE);

		g_object_set_qdata_full (G_OBJECT (doc), 
				 check_range_id, 
				 range, 
				 (GDestroyNotify)g_free);
	}

	if (gedit_spell_utils_skip_no_spell_check (start, end))
	 {
		if (!gtk_text_iter_inside_word (end))
		{
			/* if we're neither inside a word,
			 * we must be in some spaces.
			 * skip backward to the end of the previous word. */
			if (!gtk_text_iter_is_end (end))
			{
				gtk_text_iter_backward_word_start (end);
				gtk_text_iter_forward_word_end (end);
			}
		}
		else
		{
			if (!gtk_text_iter_ends_word (end))
				gtk_text_iter_forward_word_end (end);
		}
	}
	else
	{
		/* no spell checking in the specified range */
		start = end;
	}

	gtk_text_buffer_move_mark (GTK_TEXT_BUFFER (doc),
				   range->start_mark,
				   start);
	gtk_text_buffer_move_mark (GTK_TEXT_BUFFER (doc),
				   range->end_mark,
				   end);

	range->mw_start = -1;
	range->mw_end = -1;

	update_current (doc, gtk_text_iter_get_offset (start));
}
示例#15
0
文件: extra.c 项目: agaX/SpellChecker
/**
  Sprawdzenie słowa, na którym aktualnie znajduje się kursor. Ewentualne dodanie do słownika.
  @param[in] item element menu.
  @param[in] data wskaźnik na wartość.
  */
static void WhatCheck (GtkMenuItem *item, gpointer data) {
  GtkWidget *dialog;
  GtkTextIter start, end;
  char *word;
  gunichar *wword;

  //load_dictionary_from_menu(&dict);
  
  // Znajdujemy pozycję kursora
  gtk_text_buffer_get_iter_at_mark(editor_buf, &start,
                                   gtk_text_buffer_get_insert(editor_buf));

  // Jeśli nie wewnątrz słowa, kończymy
  if (!gtk_text_iter_inside_word(&start)) {
    dialog = gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_ERROR,
                                    GTK_BUTTONS_OK,
                                    "Kursor musi być w środku słowa");
    gtk_dialog_run(GTK_DIALOG(dialog));
    gtk_widget_destroy(dialog);
    return;
  }

  // Znajdujemy początek i koniec słowa, a potem samo słowo 
  end = start;
  gtk_text_iter_backward_word_start(&start);
  gtk_text_iter_forward_word_end(&end); 
  word = gtk_text_iter_get_text(&start, &end);

  // Zamieniamy na wide char (no prawie)
  wword = g_utf8_to_ucs4_fast(word, -1, NULL);
  
  if (!make_lowercase(wword)) {
    dialog = gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_INFO, GTK_BUTTONS_OK,
                                    "Podane słowo nie jest słowem słownikowym.");
    gtk_dialog_run(GTK_DIALOG(dialog));
    gtk_widget_destroy(dialog);
  }
  else {
    // Sprawdzamy
    if (dictionary_find(dict, (wchar_t *)wword)) {
      dialog = gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_INFO, GTK_BUTTONS_OK,
                                      "Wszystko w porządku,\nśpij spokojnie");
      gtk_dialog_run(GTK_DIALOG(dialog));
      gtk_widget_destroy(dialog);
    }
    else {
      // Czas korekty
      GtkWidget *vbox, *label, *combo;
      struct word_list hints;
      int i;
      wchar_t **words;

      dictionary_hints(dict, (wchar_t *)wword, &hints);
      words = (wchar_t **) word_list_get(&hints);
      dialog = gtk_dialog_new_with_buttons("Korekta", NULL, 0, 
                                           GTK_STOCK_OK,
                                           GTK_RESPONSE_ACCEPT,
                                           GTK_STOCK_ADD,
                                           GTK_RESPONSE_APPLY,
                                           GTK_STOCK_CANCEL,
                                           GTK_RESPONSE_REJECT,
                                           NULL);
      // W treści dialogu dwa elementy
      vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
      // Tekst
      label = gtk_label_new("Słowo nie znajduje się w słowniku. Wybierz \njedną z propozycji lub dodaj słowa do słownika.");
      gtk_widget_show(label);
      gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 1);

      // Spuszczane menu
      combo = gtk_combo_box_text_new();
      for (i = 0; i < word_list_size(&hints); i++) {
        // Combo box lubi mieć Gtk
        char *uword = g_ucs4_to_utf8((gunichar *)words[i], -1, NULL, NULL, NULL);

        // Dodajemy kolejny element
        gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), uword);
        g_free(uword);
      }
      gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0);
      gtk_box_pack_start(GTK_BOX(vbox), combo, FALSE, FALSE, 1);
      gtk_widget_show(combo);

      gint click = gtk_dialog_run(GTK_DIALOG(dialog));

      if (click == GTK_RESPONSE_ACCEPT) {
        char *korekta =
          gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(combo));

        // Usuwamy stare
        gtk_text_buffer_delete(editor_buf, &start, &end);
        // Wstawiamy nowe
        gtk_text_buffer_insert(editor_buf, &start, korekta, -1);
        g_free(korekta);
      }
      // Proponujemy dodanie słowa do słownika
      else if (click == GTK_RESPONSE_APPLY)
        dictionary_insert(dict, wword);
      gtk_widget_destroy(dialog);
    }
  }
  g_free(word);
  g_free(wword);
}
void CheckCapitalization::check_suspicious_capitalization(ustring & text)
/*
Checks on suspicious capitalization, like "bOat" or "BOat".
There are exceptions to this check.
*/
{
  // Load text into buffer.
  ustring text2(text);
  text2.append(" ");
  GtkTextBuffer *textbuffer;
  textbuffer = gtk_text_buffer_new(NULL);
  gtk_text_buffer_set_text(textbuffer, text2.c_str(), -1);
  // Iterators.  
  GtkTextIter startiter, enditer;
  // Check all separate words.
  gtk_text_buffer_get_start_iter(textbuffer, &enditer);
  while (gtk_text_iter_forward_word_end(&enditer)) {
    startiter = enditer;
    gtk_text_iter_backward_word_start(&startiter);
    vector < bool > capspattern;
    unsigned int capscount = 0;
    GtkTextIter iter = startiter;
    while (gtk_text_iter_in_range(&iter, &startiter, &enditer)) {
      bool upper = g_unichar_isupper(gtk_text_iter_get_char(&iter));
      capspattern.push_back(upper);
      if (upper)
        capscount++;
      gtk_text_iter_forward_char(&iter);
    }
    // No further checking if words are too short.
    if (capspattern.size() < 2)
      continue;
    // No further checking if only small letters.
    if (capscount == 0)
      continue;
    // No further checking if all capitals.
    if (capscount == capspattern.size())
      continue;
    // No further checking if first letter capitalized only.
    if ((capspattern[0]) && (capscount == 1))
      continue;
    // Ok, there could be a problem of mixed capitalization.
    // Get the prefix before the first capital, and the suffix after it.
    ustring word = gtk_text_iter_get_text(&startiter, &enditer);
    ustring uncapitalized_prefix;
    ustring capitalized_suffix;
    for (unsigned int i = 1; i < capspattern.size(); i++) {
      if (capspattern[i]) {
        uncapitalized_prefix = word.substr(0, i);
        capitalized_suffix = word.substr(i, word.length() - i);
        break;
      }
    }
    // See whether the suffix is properly capitalized.
    unsigned int suffix_capital_count = 0;
    for (unsigned int i = 0; i < capitalized_suffix.length(); i++) {
      if (g_unichar_isupper(g_utf8_get_char(capitalized_suffix.substr(i, 1).c_str())))
        suffix_capital_count++;
    }
    bool suffix_properly_capitalized = false;
    if (suffix_capital_count == 1)
      suffix_properly_capitalized = true;
    if (suffix_capital_count == capitalized_suffix.length())
      suffix_properly_capitalized = true;
    // Give message and continue if capitalization error in suffix, but only
    // if this so-called wrongly capitalized suffix has not been approved af.
    if (!suffix_properly_capitalized) {
      if (capitalized_suffixes.find(capitalized_suffix) == capitalized_suffixes.end()) {
        mixed_capitalization_message(word);
        continue;
      }
    }
    // No further checking if this uncapitalized prefix is in the list,
    // or any is allowed.
    if (uncapitalized_prefixes.find(uncapitalized_prefix) != uncapitalized_prefixes.end())
      continue;
    if (allow_any_uncapitalized_prefixes)
      continue;
    // Ok, not in the list. Try again with lower case initial.
    ustring initial = uncapitalized_prefix.substr(0, 1);
    initial = initial.casefold();
    uncapitalized_prefix.replace(0, 1, initial);
    if (uncapitalized_prefixes.find(uncapitalized_prefix) != uncapitalized_prefixes.end())
      continue;
    // No further checking if the suffix is in the list of approved suffixes.
    if (capitalized_suffixes.find(capitalized_suffix) != capitalized_suffixes.end())
      continue;
    // Ok, not found, but it could be this suffix is in all capitals. Handle that.
    initial = capitalized_suffix.substr(0, 1);
    capitalized_suffix.erase(0, 1);
    capitalized_suffix = capitalized_suffix.casefold();
    capitalized_suffix.insert(0, initial);
    if (capitalized_suffixes.find(capitalized_suffix) != capitalized_suffixes.end())
      continue;
    // Ok, it appears we've got an error here -> give message.
    mixed_capitalization_message(word);
  }
  // Free memory
  g_object_unref(textbuffer);
}
static void
check_range (GeditAutomaticSpellChecker *spell,
	     GtkTextIter                 start,
	     GtkTextIter                 end,
	     gboolean                    force_all)
{
	/* we need to "split" on word boundaries.
	 * luckily, Pango knows what "words" are
	 * so we don't have to figure it out. */

	GtkTextIter wstart;
	GtkTextIter wend;
	GtkTextIter cursor;
	GtkTextIter precursor;
  	gboolean    highlight;

	/*
	g_print ("Check range: [%d - %d]\n", gtk_text_iter_get_offset (&start),
						gtk_text_iter_get_offset (&end));
	*/

	if (gtk_text_iter_inside_word (&end))
		gtk_text_iter_forward_word_end (&end);

	if (!gtk_text_iter_starts_word (&start))
	{
		if (gtk_text_iter_inside_word (&start) ||
		    gtk_text_iter_ends_word (&start))
		{
			gtk_text_iter_backward_word_start (&start);
		}
		else
		{
			/* if we're neither at the beginning nor inside a word,
			 * me must be in some spaces.
			 * skip forward to the beginning of the next word. */

			if (gtk_text_iter_forward_word_end (&start))
				gtk_text_iter_backward_word_start (&start);
		}
	}

	gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (spell->doc),
					  &cursor,
					  gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (spell->doc)));

	precursor = cursor;
	gtk_text_iter_backward_char (&precursor);

  	highlight = gtk_text_iter_has_tag (&cursor, spell->tag_highlight) ||
  	            gtk_text_iter_has_tag (&precursor, spell->tag_highlight);

	gtk_text_buffer_remove_tag (GTK_TEXT_BUFFER (spell->doc),
				    spell->tag_highlight,
				    &start,
				    &end);

	/* Fix a corner case when replacement occurs at beginning of buffer:
	 * An iter at offset 0 seems to always be inside a word,
  	 * even if it's not.  Possibly a pango bug.
	 */
  	if (gtk_text_iter_get_offset (&start) == 0)
	{
		gtk_text_iter_forward_word_end(&start);
		gtk_text_iter_backward_word_start(&start);
	}

	wstart = start;

	while (gedit_spell_utils_skip_no_spell_check (&wstart, &end) &&
	       gtk_text_iter_compare (&wstart, &end) < 0)
	{
		gboolean inword;

		/* move wend to the end of the current word. */
		wend = wstart;

		gtk_text_iter_forward_word_end (&wend);

		inword = (gtk_text_iter_compare (&wstart, &cursor) < 0) &&
			 (gtk_text_iter_compare (&cursor, &wend) <= 0);

		if (inword && !force_all)
		{
			/* this word is being actively edited,
			 * only check if it's already highligted,
			 * otherwise defer this check until later. */
			if (highlight)
				check_word (spell, &wstart, &wend);
			else
				spell->deferred_check = TRUE;
		}
		else
		{
			check_word (spell, &wstart, &wend);
			spell->deferred_check = FALSE;
		}

		/* now move wend to the beginning of the next word, */
		gtk_text_iter_forward_word_end (&wend);
		gtk_text_iter_backward_word_start (&wend);

		/* make sure we've actually advanced
		 * (we don't advance in some corner cases), */
		if (gtk_text_iter_equal (&wstart, &wend))
			break; /* we're done in these cases.. */

		/* and then pick this as the new next word beginning. */
		wstart = wend;
	}
}
示例#18
0
static void WhatCheck (GtkMenuItem *item, gpointer data) {
  GtkWidget *dialog;
  GtkTextIter start, end;
  char *word;
  gunichar *wword;
  
  // Znajdujemy pozycję kursora
  gtk_text_buffer_get_iter_at_mark(editor_buf, &start,
                                   gtk_text_buffer_get_insert(editor_buf));

  // Jeśli nie wewnątrz słowa, kończymy
  if (!gtk_text_iter_inside_word(&start)) {
    dialog = gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_ERROR,
                                    GTK_BUTTONS_OK,
                                    "Kursor musi być w środku słowa");
    gtk_dialog_run(GTK_DIALOG(dialog));
    gtk_widget_destroy(dialog);
    return;
  }

  // Znajdujemy początek i koniec słowa, a potem samo słowo 
  end = start;
  gtk_text_iter_backward_word_start(&start);
  gtk_text_iter_forward_word_end(&end); 
  word = gtk_text_iter_get_text(&start, &end);

  // Zamieniamy na wide char (no prawie)
  wword = g_utf8_to_ucs4_fast(word, -1, NULL);

  if(update_actual_dict() < 0)
    return;
  // Sprawdzamy
  if (dictionary_find(dict, (wchar_t *)wword)) {
    dialog = gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_INFO, GTK_BUTTONS_OK,
                                    "Wszystko w porządku,\nśpij spokojnie");
    gtk_dialog_run(GTK_DIALOG(dialog));
    gtk_widget_destroy(dialog);
  }
  else {
    // Czas korekty
    GtkWidget *vbox, *label, *combo;
    struct word_list hints;
    int i;
    wchar_t **words;

    dictionary_hints(dict, (wchar_t *)wword, &hints);
    words = word_list_get(&hints);
    dialog = gtk_dialog_new_with_buttons("Korekta", NULL, 0, 
                                         GTK_STOCK_OK,
                                         GTK_RESPONSE_ACCEPT,
                                         GTK_STOCK_CANCEL,
                                         GTK_RESPONSE_REJECT,
                                         NULL);
    // W treści dialogu dwa elementy
    vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
    // Tekst
    label = gtk_label_new("Coś nie tak, mam kilka propozycji");
    gtk_widget_show(label);
    gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 1);

    // Spuszczane menu
    combo = gtk_combo_box_text_new();
    for (i = 0; i < word_list_size(&hints); i++) {
      // Combo box lubi mieć Gtk
      char *uword = g_ucs4_to_utf8((gunichar *)words[i], -1, NULL, NULL, NULL);

      // Dodajemy kolejny element
      gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), uword);
      g_free(uword);
    }
    //gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo),"<inne...>");
    gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0);
    gtk_box_pack_start(GTK_BOX(vbox), combo, FALSE, FALSE, 1);
    gtk_widget_show(combo);

    char *korekta, *question;
    GtkWidget *ask_dialog, *ask_vbox, *ask_label;
    switch (gtk_dialog_run(GTK_DIALOG(dialog))) {
      case GTK_RESPONSE_ACCEPT:
        korekta =
          gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(combo));

        // Usuwamy stare
        gtk_text_buffer_delete(editor_buf, &start, &end);
        // Wstawiamy nowe
        gtk_text_buffer_insert(editor_buf, &start, korekta, -1);
        g_free(korekta);
        break;

      case GTK_RESPONSE_REJECT:
        question = "Czy chcesz dodać to słowo do słownika?";
        ask_dialog = gtk_dialog_new_with_buttons(question, NULL, 0, 
                                                 GTK_STOCK_OK,
                                                 GTK_RESPONSE_ACCEPT,
                                                 GTK_STOCK_CANCEL,
                                                 GTK_RESPONSE_REJECT,
                                                 NULL);
        ask_vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
        // Tekst
        ask_label = gtk_label_new("Coś nie tak, mam kilka propozycji");
        gtk_widget_show(ask_label);
        gtk_box_pack_start(GTK_BOX(ask_vbox), ask_label, FALSE, FALSE, 1);

        // Jeśli chiciał dodać nowe słowo do słownika to dodamy i zapiszemy
        if (gtk_dialog_run(GTK_DIALOG(ask_dialog)) == GTK_RESPONSE_ACCEPT) {
          dictionary_insert(dict, (wchar_t *)wword);
          dictionary_save_lang(dict, dict_location);
        }
        
        gtk_widget_destroy(ask_dialog);
        break;
      }
  
    gtk_widget_destroy(dialog);
  }
  
}
示例#19
0
static void
add_chat_msg(GtTwitchChatView* self,
             const gchar* sender,
             const gchar* colour,
             const gchar* msg,
             GList* emotes,
             gint user_modes)
{
    GtTwitchChatViewPrivate* priv = gt_twitch_chat_view_get_instance_private(self);
    GtkTextTag* sender_colour_tag = NULL;
    gint offset = 0;

    gtk_text_buffer_get_end_iter(priv->chat_buffer, &priv->bottom_iter);

    if (!colour || strlen(colour) < 1) //TODO: Set random colour instead of just black
        colour = get_default_chat_colour(sender);

    sender_colour_tag = gtk_text_tag_table_lookup(priv->tag_table, colour);

    if (!sender_colour_tag)
    {
        sender_colour_tag = gtk_text_tag_new(colour);
        g_object_set(sender_colour_tag,
                     "foreground", colour,
                     "weight", PANGO_WEIGHT_BOLD,
                     NULL);
        gtk_text_tag_table_add(priv->tag_table, sender_colour_tag);
    }

    offset = strlen(sender) + 2;

    //TODO: Cleanup?
#define INSERT_USER_MOD_PIXBUF(mode, name)                              \
    if (user_modes & mode)                                              \
    {                                                                   \
        gtk_text_buffer_insert_pixbuf(priv->chat_buffer, &priv->bottom_iter, priv->chat_badges->name); \
        gtk_text_buffer_insert(priv->chat_buffer, &priv->bottom_iter, " ", -1); \
        gtk_text_iter_forward_chars(&priv->bottom_iter, 2);             \
        offset += 2;                                                    \
    }                                                                   \

    INSERT_USER_MOD_PIXBUF(USER_MODE_SUBSCRIBER, subscriber);
    INSERT_USER_MOD_PIXBUF(USER_MODE_TURBO, turbo);
    INSERT_USER_MOD_PIXBUF(USER_MODE_GLOBAL_MOD, global_mod);
    INSERT_USER_MOD_PIXBUF(USER_MODE_BROADCASTER, broadcaster);
    INSERT_USER_MOD_PIXBUF(USER_MODE_STAFF, staff);
    INSERT_USER_MOD_PIXBUF(USER_MODE_ADMIN, admin);
    INSERT_USER_MOD_PIXBUF(USER_MODE_MOD, mod);

#undef INSERT_USER_MOD_PIXBUF

    gtk_text_buffer_insert_with_tags(priv->chat_buffer, &priv->bottom_iter, sender, -1, sender_colour_tag, NULL);
    gtk_text_iter_forward_word_end(&priv->bottom_iter);
    gtk_text_buffer_insert(priv->chat_buffer, &priv->bottom_iter, ": ", -1);
    gtk_text_iter_forward_chars(&priv->bottom_iter, 2);
    insert_message_with_emotes(priv->chat_buffer, &priv->bottom_iter, emotes, msg, offset);
    gtk_text_iter_forward_to_line_end(&priv->bottom_iter);
    gtk_text_buffer_insert(priv->chat_buffer, &priv->bottom_iter, "\n", -1);
    gtk_text_buffer_move_mark(priv->chat_buffer, priv->bottom_mark, &priv->bottom_iter);
    gtk_text_view_scroll_mark_onscreen(GTK_TEXT_VIEW(priv->chat_view), priv->bottom_mark);
}
示例#20
0
bool search_in_bibledit_word_boundaries_match(const ustring & text, const ustring & searchword, bool matchbeginning, bool matchending, bool globbing)
// Does the word boundary matching.
{
  /*
     Deal with matching the start of a word and/or of the end.

     There are four cases here.
     1. Match word start only.
     2. Match word end only.
     3. Both match start end end of a word, which implies "whole word".
     4. No matching at all.

     Boundary resolution is handled by pango_break(). Textual boundaries such 
     as word boundaries and line boundaries are determined for each item.
     In most cases a general algorithm suffices for this process, but in some
     cases a language module will override the generic algorithm with a more
     specific one.
     It seems to be easier programming to use GtkTextIter and GtkTextBuffer,
     rather than pango_break() directly.
   */

  // Whether the word matches.
  bool match = false;

  // Textbuffer for determining word boundaries.
  GtkTextBuffer *textbuffer = gtk_text_buffer_new(NULL);
  gtk_text_buffer_set_text(textbuffer, text.c_str(), -1);

  // Iterators needed.
  GtkTextIter startiter;
  GtkTextIter enditer;

  // Store segments of text to compare against.
  vector < ustring > segments;

  // Deal with case one: Match word start only.  
  if (matchbeginning && !matchending) {
    // Create a patternword for the glob-style pattern matching.
    ustring patternword = searchword + "*";
    // Collect all strings starting with a word.
    gtk_text_buffer_get_start_iter(textbuffer, &startiter);
    gtk_text_buffer_get_end_iter(textbuffer, &enditer);
    while (gtk_text_iter_forward_word_end(&startiter)) {
      gtk_text_iter_backward_word_start(&startiter);
      segments.push_back(gtk_text_iter_get_text(&startiter, &enditer));
      gtk_text_iter_forward_word_end(&startiter);
    }
    // See whether the word is in it.
    for (unsigned int i2 = 0; i2 < segments.size(); i2++) {
      if (globbing) {
        // Glob-style pattern matching.
        if (g_pattern_match_simple(patternword.c_str(), segments[i2].c_str())) {
          match = true;
          break;
        }
      } else {
        // Straight compare.
        if (segments[i2].find(searchword) == 0) {
          match = true;
          break;
        }
      }
    }
  }
  // Deal with case two: Match word end only.  
  if (!matchbeginning && matchending) {
    // Create a patternword for the glob-style pattern matching.
    ustring patternword = "*" + searchword;
    // Collect all strings ending with a word.
    gtk_text_buffer_get_start_iter(textbuffer, &startiter);
    gtk_text_buffer_get_start_iter(textbuffer, &enditer);
    while (gtk_text_iter_forward_word_end(&enditer)) {
      segments.push_back(gtk_text_iter_get_text(&startiter, &enditer));
    }
    // See whether the word is in it.
    for (unsigned int i2 = 0; i2 < segments.size(); i2++) {
      if (globbing) {
        // Glob-style pattern matching.
        if (g_pattern_match_simple(patternword.c_str(), segments[i2].c_str())) {
          match = true;
          break;
        }
      } else {
        // Straight compare.
        size_t matchposition;
        matchposition = segments[i2].length() - searchword.length();
        // Negative match positions cause a false match. Solve that here.
        matchposition = CLAMP(matchposition, 0, 99999999);
        if (segments[i2].find(searchword) == matchposition) {
          match = true;
          break;
        }
      }
    }
  }
  // Deal with case three: Match both word start and end.  
  // Interpreted as "match whole word".
  if (matchbeginning && matchending) {
    // Create a patternword for the glob-style pattern matching.
    ustring patternword = searchword;
    // Collect all whole words.
    gtk_text_buffer_get_start_iter(textbuffer, &enditer);
    while (gtk_text_iter_forward_word_end(&enditer)) {
      startiter = enditer;
      gtk_text_iter_backward_word_start(&startiter);
      segments.push_back(gtk_text_iter_get_text(&startiter, &enditer));
    }
    // See whether the word is in it.
    for (unsigned int i2 = 0; i2 < segments.size(); i2++) {
      if (globbing) {
        // Glob-style pattern matching.
        if (g_pattern_match_simple(patternword.c_str(), segments[i2].c_str())) {
          match = true;
          break;
        }
      } else {
        // Straight compare.
        if (segments[i2] == searchword) {
          match = true;
          break;
        }
      }
    }
  }
  // Case four: Nothing to test, so set found to true.
  if (!matchbeginning && !matchending)
    match = true;

  // Free memory.
  g_object_unref(textbuffer);

  // Return whether match.
  return match;
}
示例#21
0
文件: main.c 项目: Distrotech/gtk
void
load_file (const gchar *demoname,
           const gchar *filename)
{
  GtkTextBuffer *info_buffer, *source_buffer;
  GtkTextIter start, end;
  char *resource_filename;
  GError *err = NULL;
  int state = 0;
  gboolean in_para = 0;
  gchar **lines;
  GBytes *bytes;
  gint i;

  if (!g_strcmp0 (current_file, filename))
    return;

  remove_data_tabs ();

  add_data_tab (demoname);

  g_free (current_file);
  current_file = g_strdup (filename);

  info_buffer = gtk_text_buffer_new (NULL);
  gtk_text_buffer_create_tag (info_buffer, "title",
                              "font", "Sans 18",
                              "pixels-below-lines", 10,
                              NULL);

  source_buffer = gtk_text_buffer_new (NULL);
  gtk_text_buffer_create_tag (source_buffer, "source",
                              "font", "monospace",
                              NULL);
  gtk_text_buffer_create_tag (source_buffer, "comment",
                              "foreground", "DodgerBlue",
                              NULL);
  gtk_text_buffer_create_tag (source_buffer, "type",
                              "foreground", "ForestGreen",
                              NULL);
  gtk_text_buffer_create_tag (source_buffer, "string",
                              "foreground", "RosyBrown",
                              "weight", PANGO_WEIGHT_BOLD,
                              NULL);
  gtk_text_buffer_create_tag (source_buffer, "control",
                              "foreground", "purple",
                              NULL);
  gtk_text_buffer_create_tag (source_buffer, "preprocessor",
                              "style", PANGO_STYLE_OBLIQUE,
                              "foreground", "burlywood4",
                              NULL);
  gtk_text_buffer_create_tag (source_buffer, "function",
                              "weight", PANGO_WEIGHT_BOLD,
                              "foreground", "DarkGoldenrod4",
                              NULL);

  resource_filename = g_strconcat ("/sources/", filename, NULL);
  bytes = g_resources_lookup_data (resource_filename, 0, &err);
  g_free (resource_filename);

  if (bytes == NULL)
    {
      g_warning ("Cannot open source for %s: %s\n", filename, err->message);
      g_error_free (err);
      return;
    }

  lines = g_strsplit (g_bytes_get_data (bytes, NULL), "\n", -1);
  g_bytes_unref (bytes);

  gtk_text_buffer_get_iter_at_offset (info_buffer, &start, 0);
  for (i = 0; lines[i] != NULL; i++)
    {
      gchar *p;
      gchar *q;
      gchar *r;

      /* Make sure \r is stripped at the end for the poor windows people */
      lines[i] = g_strchomp (lines[i]);

      p = lines[i];
      switch (state)
        {
        case 0:
          /* Reading title */
          while (*p == '/' || *p == '*' || g_ascii_isspace (*p))
            p++;
          r = p;
          while (*r != '\0')
            {
              while (*r != '/' && *r != ':' && *r != '\0')
                r++;
              if (*r == '/')
                {
                  r++;
                  p = r;
                }
              if (r[0] == ':' && r[1] == ':')
                *r = '\0';
            }
          q = p + strlen (p);
          while (q > p && g_ascii_isspace (*(q - 1)))
            q--;


          if (q > p)
            {
              int len_chars = g_utf8_pointer_to_offset (p, q);

              end = start;

              g_assert (strlen (p) >= q - p);
              gtk_text_buffer_insert (info_buffer, &end, p, q - p);
              start = end;

              gtk_text_iter_backward_chars (&start, len_chars);
              gtk_text_buffer_apply_tag_by_name (info_buffer, "title", &start, &end);

              start = end;

              while (*p && *p != '\n') p++;

              state++;
            }
          break;

        case 1:
          /* Reading body of info section */
          while (g_ascii_isspace (*p))
            p++;
          if (*p == '*' && *(p + 1) == '/')
            {
              gtk_text_buffer_get_iter_at_offset (source_buffer, &start, 0);
              state++;
            }
          else
            {
              int len;

              while (*p == '*' || g_ascii_isspace (*p))
                p++;

              len = strlen (p);
              while (g_ascii_isspace (*(p + len - 1)))
                len--;

              if (len > 0)
                {
                  if (in_para)
                    gtk_text_buffer_insert (info_buffer, &start, " ", 1);

                  g_assert (strlen (p) >= len);
                  gtk_text_buffer_insert (info_buffer, &start, p, len);
                  in_para = 1;
                }
              else
                {
                  gtk_text_buffer_insert (info_buffer, &start, "\n", 1);
                  in_para = 0;
                }
            }
          break;

        case 2:
          /* Skipping blank lines */
          while (g_ascii_isspace (*p))
            p++;
          if (*p)
            {
              p = lines[i];
              state++;
              /* Fall through */
            }
          else
            break;

        case 3:
          /* Reading program body */
          gtk_text_buffer_insert (source_buffer, &start, p, -1);
          if (lines[i+1] != NULL)
            gtk_text_buffer_insert (source_buffer, &start, "\n", 1);
          break;
        }
    }

  g_strfreev (lines);

  fontify (source_buffer);

  gtk_text_buffer_create_tag (source_buffer, "top-margin",
                              "pixels-above-lines", 20,
                              NULL);
  gtk_text_buffer_get_start_iter (source_buffer, &start);
  end = start;
  gtk_text_iter_forward_word_end (&end);
  gtk_text_buffer_apply_tag_by_name (source_buffer, "top-margin", &start, &end);

  gtk_text_buffer_create_tag (source_buffer, "bottom-margin",
                              "pixels-below-lines", 20,
                              NULL);
  gtk_text_buffer_get_end_iter (source_buffer, &end);
  start = end;
  gtk_text_iter_backward_word_start (&start);
  gtk_text_buffer_apply_tag_by_name (source_buffer, "bottom-margin", &start, &end);

  gtk_text_view_set_buffer (GTK_TEXT_VIEW (source_view), source_buffer);
  g_object_unref (source_buffer);

  gtk_text_buffer_create_tag (info_buffer, "top-margin",
                              "pixels-above-lines", 20,
                              NULL);
  gtk_text_buffer_get_start_iter (info_buffer, &start);
  end = start;
  gtk_text_iter_forward_word_end (&end);
  gtk_text_buffer_apply_tag_by_name (info_buffer, "top-margin", &start, &end);

  gtk_text_buffer_create_tag (info_buffer, "bottom-margin",
                              "pixels-below-lines", 20,
                              NULL);
  gtk_text_buffer_get_end_iter (info_buffer, &end);
  start = end;
  gtk_text_iter_backward_word_start (&start);
  gtk_text_buffer_apply_tag_by_name (info_buffer, "bottom-margin", &start, &end);

  gtk_text_view_set_buffer (GTK_TEXT_VIEW (info_view), info_buffer);
  g_object_unref (info_buffer);
}
void CheckCapitalization::check_capitalization(vector < int >&chapters, vector < ustring > &verses, ustring & text, vector < size_t > &pointers, bool end_check)
/*
Check capitalization in text.
If "end_check" is true, it also check for final sentence closing.
*/
{
  /*
     Note that this at first used gtk_text_iter_starts_sentence (&iter) and
     gtk_text_iter_ends_sentence (&iter), but these functions are not good enough,
     because do not work in several cases, like e.g. in the following line, it does
     not indicate the end of the sentence:
     As soon as the leaders of the tribes of Israel took their places, the 
     Israelites said, “How could such a horrible thing happen?"
     Therefore we use other means to check sentences.
   */

  // No check if there's no text.
  if (trim(text).empty())
    return;
  // Some variables needed.
  bool expect_capital_now = false;
  bool expect_capital_caused_by_reference = false;
  gunichar previous_char = 0;
  int localchapter = 0;
  ustring localverse = "0";
  GtkTextBuffer *textbuffer;
  textbuffer = gtk_text_buffer_new(NULL);
  gtk_text_buffer_set_text(textbuffer, text.c_str(), -1);
  GtkTextIter iter;
  gtk_text_buffer_get_start_iter(textbuffer, &iter);
  bool going = true;
  while (going) {
    // Get the unicode character.
    gunichar unichar = gtk_text_iter_get_char(&iter);
    // See whether to expect a capital now.
    if (punctuation_followed_by_capitals_set.find(unichar) != punctuation_followed_by_capitals_set.end()) {
      // Ok, expect capital.
      expect_capital_now = true;
      expect_capital_caused_by_reference = false;
      // Was this expectation caused by a reference?
      if (is_reference(iter))
        expect_capital_caused_by_reference = true;
    }
    // If we expect a capital, and we find one, no longer look for one.
    if (expect_capital_now) {
      if (g_unichar_isupper(unichar)) {
        expect_capital_now = false;
      }
    }
    // If we expect a capital, and we get lower case, that might be trouble.
    if (expect_capital_now) {
      if (g_unichar_islower(unichar)) {
        // There is no trouble if it follows a character after which to ignore lower case.
        if (ignore_lower_case_following_set.find(previous_char) != ignore_lower_case_following_set.end()) {
          expect_capital_now = false;
        }
        // If the lowercase character follows an abbreviation, there is no trouble either.
        GtkTextIter iter2 = iter;
        gtk_text_iter_backward_word_start(&iter2);
        GtkTextIter iter3 = iter2;
        gtk_text_iter_forward_word_end(&iter3);
        gtk_text_iter_forward_char(&iter3);
        ustring abbreviation = gtk_text_iter_get_text(&iter2, &iter3);
        if (abbreviations.find(abbreviation) != abbreviations.end()) {
          expect_capital_now = false;
        }
        // If it follows a reference, there is no trouble.
        if (expect_capital_caused_by_reference)
          expect_capital_now = false;
        // Ok, give message.
        if (expect_capital_now) {
          // Determine chapter and verse.
          get_chapter_and_verse(chapters, verses, pointers, iter, localchapter, localverse);
          message(book, localchapter, localverse, _("Capital expected: ") + get_context(iter));
        }
        // Only give one message about missing capitals in this context.
        expect_capital_now = false;
      }
    }
    // Store this characters as the previous characters for the next round.
    if (g_unichar_isgraph(unichar))
      previous_char = unichar;
    // Next round.
    going = gtk_text_iter_forward_char(&iter);
  }
  // The sentence should be ended with proper punctuation.
  if (end_check) {
    if (expect_capital_now)
      if (g_unichar_isdigit(previous_char))
        expect_capital_now = false;
    if (!expect_capital_now) {
      message(book, chapter, verse, _("Unended sentence: ") + get_context(iter));
    }
  }
  // Free memory
  g_object_unref(textbuffer);
}