Exemplo n.º 1
0
static gboolean
filter_zone (ClutterModel *model, ClutterModelIter *iter, gpointer user_data)
{
    MnpWorldClockPrivate *priv = GET_PRIVATE (user_data);
    char *name, *name_mem;
    GWeatherLocation *loc;
    gboolean is_first_word = TRUE, match;
    int len;
    char *key, *skey;

    if (!priv->search_text || !*priv->search_text)
        return TRUE;

    skey = key = g_ascii_strdown(priv->search_text, -1);
    clutter_model_iter_get (iter,
                            GWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, &name_mem,
                            GWEATHER_LOCATION_ENTRY_COL_LOCATION, &loc,
                            -1);
    name = name_mem;

    if (!loc) {
        g_free (name_mem);
        g_free (key);
        return FALSE;
    }

    /* All but the last word in KEY must match a full word from NAME,
     * in order (but possibly skipping some words from NAME).
     */
    len = strcspn (key, " ");
    while (key[len]) {
        name = find_word (name, key, len, TRUE, is_first_word);
        if (!name) {
            g_free (name_mem);
            g_free (skey);
            return FALSE;
        }

        key += len;
        while (*key && !g_unichar_isalpha (g_utf8_get_char (key)))
            key = g_utf8_next_char (key);
        while (*name && !g_unichar_isalpha (g_utf8_get_char (name)))
            name = g_utf8_next_char (name);

        len = strcspn (key, " ");
        is_first_word = FALSE;
    }

    /* The last word in KEY must match a prefix of a following word in NAME */
    match = find_word (name, key, strlen (key), FALSE, is_first_word) != NULL;
    g_free (name_mem);
    g_free (skey);
    return match;
}
Exemplo n.º 2
0
static void
cb_entry_insert_text (GtkEditable *editable,
		      gchar const *text,
		      gint         len_bytes,
		      gint        *pos_in_chars,
		      WBCGtk *wbcg)
{
	char const *str = gtk_entry_get_text (GTK_ENTRY (editable));
	int pos_in_bytes = g_utf8_offset_to_pointer (str, *pos_in_chars) - str;

	if (wbcg->auto_completing &&
	    len_bytes != 0 &&
	    (!g_unichar_isalpha (g_utf8_get_char (text)) ||
	     *pos_in_chars != gtk_entry_get_text_length (GTK_ENTRY (editable)))) {
		wbcg->auto_completing = FALSE;
	}

	if (wbcg->edit_line.full_content) {
		(void)pango_attr_list_filter (wbcg->edit_line.cur_fmt,
					      cb_set_attr_list_len,
					      GINT_TO_POINTER (len_bytes));

		go_pango_attr_list_open_hole (wbcg->edit_line.full_content,
					      pos_in_bytes, len_bytes);
		pango_attr_list_splice (wbcg->edit_line.full_content,
					wbcg->edit_line.cur_fmt,
					pos_in_bytes, 0);

		go_pango_attr_list_open_hole (wbcg->edit_line.markup,
					      pos_in_bytes, len_bytes);
		pango_attr_list_splice (wbcg->edit_line.markup,
					wbcg->edit_line.cur_fmt,
					pos_in_bytes, 0);
	}
}
Exemplo n.º 3
0
void TextEdit::setFlags(int new_flags, bool revalidate)
{
  if (new_flags == flags)
    return;

  flags = new_flags;

  if (flags && revalidate) {
    bool valid = true;
    const char *p = getTextStart();
    while (p < bufend - 1) {
      gunichar uc = g_utf8_get_char(p);
      if ((flags & FLAG_ALPHABETIC) && !g_unichar_isalpha(uc)) {
        valid = false;
        break;
      }
      if ((flags & FLAG_NUMERIC) && !g_unichar_isdigit(uc)) {
        valid = false;
        break;
      }
      if ((flags & FLAG_NOSPACE) && g_unichar_isspace(uc)) {
        valid = false;
        break;
      }
      if ((flags & FLAG_NOPUNCTUATION) && g_unichar_ispunct(uc)) {
        valid = false;
        break;
      }
      p = nextChar(p);
    }
    if (!valid)
      clear();
  }
}
Exemplo n.º 4
0
static SearchCase
inspect_case (const char *p, const char *pend)
{
	gboolean is_upper = TRUE;
	gboolean is_capital = TRUE;
	gboolean has_letter = FALSE;
	gboolean expect_upper = TRUE;

	for (; p < pend; p = g_utf8_next_char (p)) {
		gunichar c = g_utf8_get_char (p);
		if (g_unichar_isalpha (c)) {
			has_letter = TRUE;
			if (!g_unichar_isupper (c)) {
				is_upper = FALSE;
			}

			if (expect_upper ? !g_unichar_isupper (c) : !g_unichar_islower (c)) {
				is_capital = FALSE;
			}
			expect_upper = FALSE;
		} else
			expect_upper = TRUE;
	}

	if (has_letter) {
		if (is_upper)
			return SC_Upper;
		if (is_capital)
			return SC_Capital;
	}

	return SC_Other;
}
Exemplo n.º 5
0
/*
 *  call-seq:
 *    utf8_titleize(string)
 *
 *  Returns a title case string.
 *
 *    Glib.utf8_titleize('привет всем') #=> Привет Всем
 */
static VALUE utf8_titleize(VALUE self, VALUE string)
{
  VALUE result;
  gchar *temp;
  long index, length_in_bytes, length_in_chars;
  gunichar *chars_as_ucs4, current_char;
  gboolean first_character_of_word = TRUE;

  Check_Type(string, T_STRING);

  length_in_bytes = RSTRING_LEN(string);
  if ((chars_as_ucs4 = g_utf8_to_ucs4(StringValuePtr(string), length_in_bytes, NULL, &length_in_chars, NULL))) {
    for (index = 0; index < length_in_chars; index++) {
      current_char = chars_as_ucs4[index];
      if (first_character_of_word == TRUE && g_unichar_isalpha(current_char)) {
        chars_as_ucs4[index] = g_unichar_totitle(current_char);
        first_character_of_word = FALSE;
      }

      if (g_unichar_isspace(current_char) || g_unichar_ispunct(current_char)) {
        first_character_of_word = TRUE;
      }
    }
    
    temp = g_ucs4_to_utf8(chars_as_ucs4, -1, NULL, NULL, NULL);
    result = rb_str_new2(temp);
    g_free(chars_as_ucs4);
    g_free(temp);
    
    return result;
  } else {
    return Qnil;
  }
}
Exemplo n.º 6
0
static bool _tokenize_identifier(GSDLTokenizer *self, GSDLToken *result, gunichar c, GError **err) {
	int length = 7;
	char *output = result->val = g_malloc(length);
	GUnicodeType type;

	int i = g_unichar_to_utf8(c, output);

	while (_peek(self, &c, err) && (c == '-' || c == '.' || g_unichar_isalpha(c) || g_unichar_isdigit(c) || (type = g_unichar_type(c)) == G_UNICODE_CURRENCY_SYMBOL || type == G_UNICODE_CONNECT_PUNCTUATION || type == G_UNICODE_LETTER_NUMBER || type == G_UNICODE_SPACING_MARK || type == G_UNICODE_NON_SPACING_MARK)) {
		GROW_IF_NEEDED(output = result->val, i + 5, length);

		_consume(self);
		i += g_unichar_to_utf8(c, output + i);
	}

	FAIL_IF_ERR();
	output[i] = '\0';

	if (
			strcmp(output, "true") == 0 ||
			strcmp(output, "on") == 0 ||
			strcmp(output, "false") == 0 ||
			strcmp(output, "off") == 0) {
		result->type = T_BOOLEAN;
	} else if (strcmp(output, "null") == 0) {
		result->type = T_NULL;
	}

	return true;
}
Exemplo n.º 7
0
static gboolean
gimp_eevl_unit_identifier_start (gunichar c)
{
  return (g_unichar_isalpha (c) ||
          c == (gunichar) '%'   ||
          c == (gunichar) '\'');
}
Exemplo n.º 8
0
static gchar *
e_name_western_get_one_prefix_at_str (gchar *str)
{
	gchar *word;
	gint   i;

	/*
	 * Check for prefixes from our table.
	 */
	for (i = 0; i < G_N_ELEMENTS (western_pfx_index); i++) {
		gint pfx_words;
		const gchar *prefix;
		gchar *words;
		gchar *folded_words;

		prefix = western_pfx_table + western_pfx_index[i];
		pfx_words = e_name_western_str_count_words (prefix);
		words = e_name_western_get_words_at_idx (str, 0, pfx_words);
		folded_words = g_utf8_casefold (words, -1);

		if (!g_utf8_collate (folded_words, prefix)) {
			g_free (folded_words);
			return words;
		}
		g_free (folded_words);
		g_free (words);
	}

	/*
	 * Check for prefixes we don't know about.  These are always a
	 * sequence of more than one letters followed by a period.
	 */
	word = e_name_western_get_words_at_idx (str, 0, 1);

	if (g_utf8_strlen (word, -1) > 2 &&
	    g_unichar_isalpha (g_utf8_get_char (word)) &&
	    g_unichar_isalpha (g_utf8_get_char (g_utf8_next_char (word))) &&
	    word[strlen (word) - 1] == '.')
		return word;

	g_free (word);

	return NULL;
}
Exemplo n.º 9
0
gboolean
alert_match_text (char *text, char *masks)
{
    unsigned char *p = text;
    unsigned char endchar;
    int res;

    if (masks[0] == 0)
        return FALSE;

    while (1)
    {
        if (*p >= '0' && *p <= '9')
        {
            p++;
            continue;
        }

        /* if it's RFC1459 <special>, it can be inside a word */
        switch (*p)
        {
        case '-':
        case '[':
        case ']':
        case '\\':
        case '`':
        case '^':
        case '{':
        case '}':
        case '_':
        case '|':
            p++;
            continue;
        }

        /* if it's a 0, space or comma, the word has ended. */
        if (*p == 0 || *p == ' ' || *p == ',' ||
                /* if it's anything BUT a letter, the word has ended. */
                (!g_unichar_isalpha (g_utf8_get_char (p))))
        {
            endchar = *p;
            *p = 0;
            res = alert_match_word (text, masks);
            *p = endchar;

            if (res)
                return TRUE;        /* yes, matched! */

            text = p + g_utf8_skip[p[0]];
            if (*p == 0)
                return FALSE;
        }

        p += g_utf8_skip[p[0]];
    }
}
Exemplo n.º 10
0
gchar *
mousepad_util_utf8_strcapital (const gchar *str)
{
  gunichar     c;
  const gchar *p;
  gchar       *buf;
  GString     *result;
  gboolean     upper = TRUE;

  g_return_val_if_fail (g_utf8_validate (str, -1, NULL), NULL);

  /* create a new string */
  result = g_string_sized_new (strlen (str));

  /* walk though the string */
  for (p = str; *p != '\0'; p = g_utf8_next_char (p))
    {
      /* get the unicode char */
      c = g_utf8_get_char (p);

      /* only change the case of alpha chars */
      if (g_unichar_isalpha (c))
        {
          /* check case */
          if (upper ? g_unichar_isupper (c) : g_unichar_islower (c))
            {
              /* currect case is already correct */
              g_string_append_unichar (result, c);
            }
          else
            {
              /* convert the case of the char and append it */
              buf = upper ? g_utf8_strup (p, 1) : g_utf8_strdown (p, 1);
              g_string_append (result, buf);
              g_free (buf);
            }

          /* next char must be lowercase */
          upper = FALSE;
        }
      else
        {
          /* append the char */
          g_string_append_unichar (result, c);

          /* next alpha char uppercase after a space */
          upper = g_unichar_isspace (c);
        }
    }

  /* return the result */
  return g_string_free (result, FALSE);
}
Exemplo n.º 11
0
static void
gnc_price_cell_modify_verify (BasicCell *_cell,
                              const char *change,
                              int change_len,
                              const char *newval,
                              int newval_len,
                              int *cursor_position,
                              int *start_selection,
                              int *end_selection)
{
    PriceCell *cell = (PriceCell *) _cell;
    struct lconv *lc = gnc_localeconv ();
    const char *toks = "+-*/=()_";
    gunichar decimal_point;
    gunichar thousands_sep;
    const char *c;
    gunichar uc;

    /* accept the newval string if user action was delete */
    if (change == NULL)
    {
        gnc_basic_cell_set_value_internal (_cell, newval);
        cell->need_to_parse = TRUE;
        return;
    }

    if (cell->print_info.monetary)
        decimal_point = g_utf8_get_char(lc->mon_decimal_point);
    else
        decimal_point = g_utf8_get_char(lc->decimal_point);

    if (cell->print_info.monetary)
        thousands_sep = g_utf8_get_char(lc->mon_thousands_sep);
    else
        thousands_sep = g_utf8_get_char(lc->thousands_sep);

    c = change;
    while (*c)
    {
        uc = g_utf8_get_char (c);
        if (!g_unichar_isdigit (uc) &&
                !g_unichar_isspace (uc) &&
                !g_unichar_isalpha (uc) &&
                (decimal_point != uc) &&
                (thousands_sep != uc) &&
                (g_utf8_strchr (toks, -1, uc) == NULL))
            return;
        c = g_utf8_next_char (c);
    }

    gnc_basic_cell_set_value_internal (_cell, newval);
    cell->need_to_parse = TRUE;
}
Exemplo n.º 12
0
//Finds out if the result is EXACT_MATCH, START_WITH_MATCH, END_WITH_MATCH, ANY_MATCH
int get_jp_match_type(gchar *line, gchar *srchstrg, int offset) {
  int srchstrglen;

  srchstrglen = strlen(srchstrg);
  if (offset == 0) { //can be EXACT or START_WITH
    if ((*(line + srchstrglen)) == ' ') return EXACT_MATCH;
    return START_WITH_MATCH;
  }
  else { //Check for Furigana
    if (g_unichar_isalpha(g_utf8_get_char(g_utf8_prev_char(line + offset))) == FALSE) {
      if (g_unichar_isalpha(g_utf8_get_char(line + offset + srchstrglen)) == FALSE) {
				return EXACT_MATCH;
      }
      else return START_WITH_MATCH;
    }
    else { // has an alpha char before
      if (g_unichar_isalpha(g_utf8_get_char(line + offset + srchstrglen)) == FALSE)
				return END_WITH_MATCH;
    }
  }
  if ((*(line + offset + srchstrglen)) == ' ') return END_WITH_MATCH;
  return ANY_MATCH;
}
Exemplo n.º 13
0
static char *
find_word (const char *full_name, const char *word, int word_len,
           gboolean whole_word, gboolean is_first_word)
{
    char *p = (char *)full_name - 1;

    while ((p = strchr (p + 1, *word))) {
        if (strncmp (p, word, word_len) != 0)
            continue;

        if (p > (char *)full_name) {
            char *prev = g_utf8_prev_char (p);

            /* Make sure p points to the start of a word */
            if (g_unichar_isalpha (g_utf8_get_char (prev)))
                continue;

            /* If we're matching the first word of the key, it has to
             * match the first word of the location, city, state, or
             * country. Eg, it either matches the start of the string
             * (which we already know it doesn't at this point) or
             * it is preceded by the string ", " (which isn't actually
             * a perfect test. FIXME)
             */
            if (is_first_word) {
                if (prev == (char *)full_name || strncmp (prev - 1, ", ", 2) != 0)
                    continue;
            }
        }

        if (whole_word && g_unichar_isalpha (g_utf8_get_char (p + word_len)))
            continue;

        return p;
    }
    return NULL;
}
static gunichar
get_first_non_underscore_char (const char *str)
{
    const char *p;

    if (!str)
        return 0;

    for (p = str; p && *p; p = g_utf8_find_next_char (p, NULL))
    {
        gunichar ch;

        ch = g_utf8_get_char (p);
        if (g_unichar_isalpha (ch))
            return ch;
    }

    return 0;
}
Exemplo n.º 15
0
/**
 * expr_name_validate:
 * @name: tentative name
 *
 * returns TRUE if the given name is valid, FALSE otherwise.
 */
gboolean
expr_name_validate (const char *name)
{
	const char *p;
	GnmValue *v;

	g_return_val_if_fail (name != NULL, FALSE);

	if (name[0] == 0)
		return FALSE;

	v = value_new_from_string (VALUE_BOOLEAN, name, NULL, TRUE);
	if (!v)
		v = value_new_from_string (VALUE_BOOLEAN, name, NULL, FALSE);
	if (v) {
		value_release (v);
		return FALSE;
	}

	/* Hmm...   Now what?  */
	if (!g_unichar_isalpha (g_utf8_get_char (name)) &&
	    name[0] != '_')
		return FALSE;

	for (p = name; *p; p = g_utf8_next_char (p)) {
		if (!g_unichar_isalnum (g_utf8_get_char (p)) &&
		    p[0] != '_')
			return FALSE;
	}

	/* Make sure it's not A1 etc.*/
	/* Note that we can't use our regular parsers */
	/* since we also have to avoid names that may become */
	/* sensible when the sheet size changes. */
	if (!expr_name_validate_a1 (name))
		return FALSE;

	/* What about R1C1?  */
	if (!expr_name_validate_r1c1 (name))
		return FALSE;

	return TRUE;
}
Exemplo n.º 16
0
gchar *
mousepad_util_utf8_stropposite (const gchar *str)
{
  gunichar     c;
  const gchar *p;
  gchar       *buf;
  GString     *result;

  g_return_val_if_fail (g_utf8_validate (str, -1, NULL), NULL);

  /* create a new string */
  result = g_string_sized_new (strlen (str));

  /* walk though the string */
  for (p = str; *p != '\0'; p = g_utf8_next_char (p))
    {
      /* get the unicode char */
      c = g_utf8_get_char (p);

      /* only change the case of alpha chars */
      if (g_unichar_isalpha (c))
        {
          /* get the opposite case of the char */
          if (g_unichar_isupper (c))
            buf = g_utf8_strdown (p, 1);
          else
            buf = g_utf8_strup (p, 1);

          /* append to the buffer */
          g_string_append (result, buf);
          g_free (buf);
        }
      else
        {
          /* append the char */
          g_string_append_unichar (result, c);
        }
    }

  /* return the result */
  return g_string_free (result, FALSE);
}
Exemplo n.º 17
0
static gboolean
gtkspell_text_iter_backward_word_start(GtkTextIter *i) {
	GtkTextIter iter;

	if (!gtk_text_iter_backward_word_start(i))
		return FALSE;

	iter = *i;
	if (gtk_text_iter_backward_char(&iter)) {
		if (gtk_text_iter_get_char(&iter) == '\'') {
			if (gtk_text_iter_backward_char(&iter)) {
				if (g_unichar_isalpha(gtk_text_iter_get_char(&iter))) {
					return (gtk_text_iter_backward_word_start(i));
				}
			}
		}
	}

	return TRUE;
}
Exemplo n.º 18
0
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;
}
Exemplo n.º 19
0
/** Examine an extension menu item and see if it needs to have an
 *  accelerator key assigned to it.  If so, find the first character
 *  in the menu name that isn't already assigned as an accelerator in
 *  the same menu, assign it to this item, and add it to the map of
 *  already used accelerator keys.  These maps are maintained per
 *  path, so accelerator keys may be duplicated across different menus
 *  but are guaranteed to be unique within any given menu.
 *
 *  @param info A menu extension.
 *
 *  @param table A hash table of accelerator maps. */
static void
gnc_menu_additions_assign_accel (ExtensionInfo *info, GHashTable *table)
{
    gchar *map, *new_map, *new_label, *start, buf[16];
    const gchar *ptr;
    gunichar uni;
    gint len;
    gboolean map_allocated = FALSE;

    ENTER("Checking %s/%s [%s]", info->path, info->ae.label, info->ae.name);
    if (info->accel_assigned)
    {
        LEAVE("Already processed");
        return;
    }

    /* Get map of used keys */
    map = g_hash_table_lookup(table, info->path);
    if (map == NULL)
    {
        map = g_strdup("");
        map_allocated = TRUE;
    }
    DEBUG("map '%s', path %s", map, info->path);

    for (ptr = info->ae.label; *ptr; ptr = g_utf8_next_char(ptr))
    {
        uni = g_utf8_get_char(ptr);
        if (!g_unichar_isalpha(uni))
            continue;
        uni = g_unichar_tolower(uni);
        len = g_unichar_to_utf8(uni, buf);
        buf[len] = '\0';
        DEBUG("Testing character '%s'", buf);
        if (!g_utf8_strchr(map, -1, uni))
            break;
    }

    if (ptr == NULL)
    {
        /* Ran out of characters. Nothing to do. */
        info->accel_assigned = TRUE;
        if (map_allocated)
        {
            g_free(map);
        }
        LEAVE("All characters already assigned");
        return;
    }

    /* Now build a new string in the form "<start>_<end>". */
    start = g_strndup(info->ae.label, ptr - info->ae.label);
    DEBUG("start %p, len %ld, text '%s'", start, g_utf8_strlen(start, -1), start);
    new_label = g_strconcat(start, "_", ptr, (gchar *)NULL);
    g_free(start);
    DEBUG("label '%s' -> '%s'", info->ae.label, new_label);
    g_free((gchar *)info->ae.label);
    info->ae.label = new_label;

    /* Now build a new map. Old one freed automatically. */
    new_map = g_strconcat(map, buf, (gchar *)NULL);
    DEBUG("map '%s' -> '%s'", map, new_map);
    g_hash_table_replace(table, info->path, new_map);

    info->accel_assigned = TRUE;
    if (map_allocated)
    {
        g_free(map);
    }
    LEAVE("assigned");
}
Exemplo n.º 20
0
static void
property_dialog_add_cb (GtkWidget *button,
			GtkWidget *dialog)
{
	PlannerPropertyDialogPriv *priv;
	MrpPropertyType            type;
	const gchar               *label;
	const gchar               *name;
	const gchar               *description;
	GladeXML                  *glade;
	GtkWidget                 *label_entry;
	GtkWidget                 *name_entry;
	GtkWidget                 *add_dialog;
	GtkWidget                 *w;
	gint                       response;
	gboolean                   finished = FALSE;
	gunichar                   c;
	gchar                     *filename;

	priv = GET_PRIV (dialog);

	filename = mrp_paths_get_glade_dir ("new-property.glade");
	glade = glade_xml_new (filename,
			       NULL,
			       NULL);
	g_free (filename);

	add_dialog = glade_xml_get_widget (glade, "add_dialog");

	label_entry = glade_xml_get_widget (glade, "label_entry");
	name_entry = glade_xml_get_widget (glade, "name_entry");

	g_signal_connect (label_entry,
			  "focus_out_event",
			  G_CALLBACK (property_dialog_label_changed_cb),
			  name_entry);

	property_dialog_setup_option_menu (
		glade_xml_get_widget (glade, "type_menu"),
		G_CALLBACK (property_dialog_type_selected_cb),
		add_dialog,
		mrp_property_type_as_string (MRP_PROPERTY_TYPE_STRING),
		MRP_PROPERTY_TYPE_STRING,
		mrp_property_type_as_string (MRP_PROPERTY_TYPE_INT),
		MRP_PROPERTY_TYPE_INT,
		mrp_property_type_as_string (MRP_PROPERTY_TYPE_FLOAT),
		MRP_PROPERTY_TYPE_FLOAT,
/*  		mrp_property_type_as_string (MRP_PROPERTY_TYPE_DATE), */
/*  		MRP_PROPERTY_TYPE_DATE, */
/*  		mrp_property_type_as_string (MRP_PROPERTY_TYPE_DURATION), */
/*  		MRP_PROPERTY_TYPE_DURATION, */
/* 		mrp_property_type_as_string (MRP_PROPERTY_TYPE_COST), */
/*  		MRP_PROPERTY_TYPE_COST, */
		NULL);

	while (!finished) {
		response = gtk_dialog_run (GTK_DIALOG (add_dialog));

		switch (response) {
		case GTK_RESPONSE_OK:
			label = gtk_entry_get_text (GTK_ENTRY (label_entry));
			if (label == NULL || label[0] == 0) {
				finished = FALSE;
				break;
			}

			name = gtk_entry_get_text (GTK_ENTRY (name_entry));
			if (name == NULL || name[0] == 0) {
				finished = FALSE;
				break;
			}

			c = g_utf8_get_char (name);
			if (!g_unichar_isalpha (c)) {
				GtkWidget *msg_dialog;

				msg_dialog = gtk_message_dialog_new (
					GTK_WINDOW (add_dialog),
					GTK_DIALOG_MODAL |
					GTK_DIALOG_DESTROY_WITH_PARENT,
					GTK_MESSAGE_WARNING,
					GTK_BUTTONS_OK,
					_("The name of the custom property needs to start with a letter."));

				gtk_dialog_run (GTK_DIALOG (msg_dialog));
				gtk_widget_destroy (msg_dialog);

				finished = FALSE;
				break;
			}

			w = glade_xml_get_widget (glade, "description_entry");
			description = gtk_entry_get_text (GTK_ENTRY (w));

			w = glade_xml_get_widget (glade, "type_menu");
			type = property_dialog_get_selected (w);

			if (type != MRP_PROPERTY_TYPE_NONE) {
				property_cmd_add (priv->main_window,
						  priv->project,
						  priv->owner,
						  name,
						  type,
						  label,
						  description,
						  TRUE);
			}

			finished = TRUE;
			break;

		case GTK_RESPONSE_DELETE_EVENT:
		case GTK_RESPONSE_CANCEL:
			finished = TRUE;
			break;

		default:
			break;
		}
	}

 	gtk_widget_destroy (add_dialog);
	g_object_unref (glade);
}
Exemplo n.º 21
0
/**********************************************************************
 * Takes text and make a list of words, one per line, validating as UTF-8
 */
gchar *
velo_filter_utf8 (gchar * text)
{
	gunichar uch;
	gboolean is_searching_word;
	struct INPUT_TEXT
	{
		gchar *pt;
		gulong len;
		guint nwords;
	} raw;
	struct FILTERED_TEXT
	{
		gchar *txt;
		gulong i;
		gulong len;
	} flt;

	raw.len = strlen (text);

	/* Verify empty string
	 */
	if (raw.len == 0)
	{
		flt.txt = g_strdup ("01234\n56789\n43210\n98765\n:-)\n");
		return (flt.txt);
	}

	/* Allocate memory space for the result
	 */
	flt.i = 0;
	flt.len = raw.len + 1024;
	flt.txt = g_malloc (flt.len);

	raw.pt = text;

	/* Filter
	 */
	raw.nwords = 0;
	is_searching_word = TRUE;
	while (raw.pt && raw.nwords < MAX_WORDS)
	{
		if (*raw.pt == '\0')
			break;

		/* Read valid utf8 char
		 */
		if ((uch = g_utf8_get_char_validated (raw.pt, -1)) == (gunichar) - 1
		    || uch == (gunichar) - 2)
			uch = L' ';

		/* Increase the pointer for the input text
		 */
		raw.pt = g_utf8_find_next_char (raw.pt, NULL);

		/* Verify memory space of output buffer
		 */
		if (flt.i < flt.len - 8)
		{
			flt.len += 1024;
			flt.txt = g_realloc (flt.txt, flt.len);
		}

		/* Test alphabetic char to form a word
		 */
		if (g_unichar_isalpha (uch))
		{
			flt.i += g_unichar_to_utf8 (uch, &flt.txt[flt.i]);
			is_searching_word = FALSE;
		}
		else if (!is_searching_word)
		{
			raw.nwords++;
			flt.txt[flt.i++] = '\n';
			is_searching_word = TRUE;
		}
	}
	flt.txt[flt.i++] = '\0';

	if (raw.nwords == 0)
	{
		g_free (flt.txt);
		flt.txt = g_strdup ("01234\n56789\n43210\n98765\n:-)\n");
	}

	return (flt.txt);
}
Exemplo n.º 22
0
/**
 * wbcg_edit_start:
 * @wbcg:       The workbook to be edited.
 * @blankp:   If true, erase current cell contents first.  If false, leave the
 *            contents alone.
 * @cursorp:  If true, create an editing cursor in the current sheet.  (If
 *            false, the text will be editing in the edit box above the sheet,
 *            but this is not handled by this function.)
 *
 * Initiate editing of a cell in the sheet.  Note that we have two modes of
 * editing:
 *  1) in-cell editing when you just start typing, and
 *  2) above sheet editing when you hit F2.
 *
 * Returns TRUE if we did indeed start editing.  Returns FALSE if the
 * cell-to-be-edited was locked.
 */
gboolean
wbcg_edit_start (WBCGtk *wbcg,
		 gboolean blankp, gboolean cursorp)
{
	/* We could save this, but the situation is rare, if confusing.  */
	static gboolean warn_on_text_format = TRUE;
	SheetView *sv;
	SheetControlGUI *scg;
	GnmCell *cell;
	char *text = NULL;
	int col, row;
	WorkbookView *wbv;
	int cursor_pos = -1;

	g_return_val_if_fail (GNM_IS_WBC_GTK (wbcg), FALSE);

	if (wbcg_is_editing (wbcg))
		return TRUE;

	/* Avoid recursion, and do not begin editing if a guru is up */
	if (wbcg->inside_editing || wbc_gtk_get_guru (wbcg) != NULL)
		return TRUE;
	wbcg->inside_editing = TRUE;

	wbv = wb_control_view (GNM_WBC (wbcg));
	sv = wb_control_cur_sheet_view (GNM_WBC (wbcg));
	scg = wbcg_cur_scg (wbcg);

	col = sv->edit_pos.col;
	row = sv->edit_pos.row;

	/* don't edit a locked cell */
	/* TODO : extend this to disable edits that cannot succeed
	 * like editing a single cell of an array.  I think we have enough
	 * information if we look at the selection.
	 */
	if (wb_view_is_protected (wbv, TRUE) &&
	    gnm_style_get_contents_locked (sheet_style_get (sv->sheet, col, row))) {
		char *pos =  g_strdup_printf ( _("%s!%s is locked"),
			sv->sheet->name_quoted, cell_coord_name (col, row));
		go_cmd_context_error_invalid (GO_CMD_CONTEXT (wbcg), pos,
			wb_view_is_protected (wbv, FALSE)
			 ? _("Unprotect the workbook to enable editing.")
			 : _("Unprotect the sheet to enable editing."));
		wbcg->inside_editing = FALSE;
		g_free (pos);
		return FALSE;
	}

	cell = sheet_cell_get (sv->sheet, col, row);
	if (cell &&
	    warn_on_text_format &&
	    go_format_is_text (gnm_cell_get_format (cell)) &&
	    (gnm_cell_has_expr (cell) || !VALUE_IS_STRING (cell->value))) {
		gint res; /* Using GtkResponseType would yield a warning on the switch */
		GtkWidget *check;
		GtkWidget *align;

		GtkWidget *d = gnm_message_dialog_create
			(wbcg_toplevel (wbcg),
			 GTK_DIALOG_DESTROY_WITH_PARENT,
			 GTK_MESSAGE_WARNING,
			 _("You are about to edit a cell with \"text\" format."),
			 _("The cell does not currently contain text, though, so if "
			   "you go on editing then the contents will be turned into "
			   "text."));
		gtk_dialog_add_button (GTK_DIALOG (d), GTK_STOCK_EDIT, GTK_RESPONSE_OK);
		go_gtk_dialog_add_button
			(GTK_DIALOG (d), _("Remove format"), GTK_STOCK_REMOVE,
			 GNM_RESPONSE_REMOVE);
		gtk_dialog_add_button (GTK_DIALOG (d), GNM_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
		gtk_dialog_set_default_response (GTK_DIALOG (d), GTK_RESPONSE_CANCEL);

		check = gtk_check_button_new_with_label (_("Show this dialog next time."));
		g_signal_connect (check, "toggled", G_CALLBACK (cb_warn_toggled), &warn_on_text_format);
		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), TRUE);
		align = gtk_alignment_new (0.5, 0.5, 0, 0);
		gtk_container_add (GTK_CONTAINER (align), check);
		gtk_widget_show_all (align);
		gtk_box_pack_end (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (d))), align, TRUE, TRUE, 0);
		res = go_gtk_dialog_run (GTK_DIALOG (d), wbcg_toplevel (wbcg));

		switch (res) {
		case GNM_RESPONSE_REMOVE: {
			GnmStyle *style = gnm_style_new ();
			gnm_style_set_format (style, go_format_general ());
			if (!cmd_selection_format (GNM_WBC (wbcg),
						   style, NULL, NULL))
				break;
			/* Fall through.  */
		}
		default:
		case GTK_RESPONSE_CANCEL:
			wbcg->inside_editing = FALSE;
			return FALSE;
		case GTK_RESPONSE_OK:
			break;
		}
	}

	gnm_app_clipboard_unant ();

	if (blankp)
		gtk_entry_set_text (wbcg_get_entry (wbcg), "");
	else if (cell != NULL) {
		gboolean quoted = FALSE;

		text = gnm_cell_get_text_for_editing (cell, sv->sheet, &quoted, &cursor_pos);

		if (text)
			gtk_entry_set_text (wbcg_get_entry (wbcg), text);

		if (cell->value != NULL) {
			GOFormat const *fmt = VALUE_FMT (cell->value);
			if (fmt != NULL && go_format_is_markup (fmt)) {
				PangoAttrList *markup =
					pango_attr_list_copy ((PangoAttrList *)go_format_get_markup (fmt));
				if (quoted)
					go_pango_attr_list_open_hole (markup, 0, 1);
				wbcg_edit_init_markup (wbcg, markup);
			}
		}
	}

	gnm_expr_entry_set_scg (wbcg->edit_line.entry, scg);
	gnm_expr_entry_set_flags (wbcg->edit_line.entry,
		GNM_EE_SHEET_OPTIONAL | GNM_EE_FORMULA_ONLY,
		GNM_EE_SINGLE_RANGE | GNM_EE_SHEET_OPTIONAL | GNM_EE_FORMULA_ONLY | GNM_EE_FORCE_REL_REF | GNM_EE_FORCE_ABS_REF);
	scg_edit_start (scg);

	/* Redraw the cell contents in case there was a span */
	sheet_redraw_region (sv->sheet, col, row, col, row);

	if (cursorp && /* autocompletion code will not work in the edit line */
	    wbv->do_auto_completion &&
	    (text == NULL || g_unichar_isalpha (g_utf8_get_char (text)))) {
		wbcg->auto_complete = gnm_complete_sheet_new (
			sv->sheet, col, row,
			workbook_edit_complete_notify, wbcg);
		wbcg->auto_completing = TRUE;
		wbcg->auto_max_size = 0;
	} else
		wbcg->auto_complete = NULL;

	/* Give the focus to the edit line */
	if (!cursorp)
		gtk_window_set_focus (wbcg_toplevel (wbcg),
			(GtkWidget *) wbcg_get_entry (wbcg));

	wbcg->editing = TRUE;
	wbcg->editing_sheet = sv->sheet;
	wbcg->editing_cell = cell;

	/* If this assert fails, it means editing was not shut down
	 * properly before
	 */
	g_return_val_if_fail (wbcg->edit_line.signal_changed == 0, TRUE);
	wbcg->edit_line.signal_changed = g_signal_connect (
		G_OBJECT (wbcg_get_entry (wbcg)),
		"changed",
		G_CALLBACK (cb_entry_changed), wbcg);
	wbcg->edit_line.signal_insert = g_signal_connect (
		G_OBJECT (wbcg_get_entry (wbcg)),
		"insert-text",
		G_CALLBACK (cb_entry_insert_text), wbcg);
	wbcg->edit_line.signal_delete = g_signal_connect (
		G_OBJECT (wbcg_get_entry (wbcg)),
		"delete-text",
		G_CALLBACK (cb_entry_delete_text), wbcg);
	wbcg->edit_line.signal_cursor_pos = g_signal_connect_swapped (
		G_OBJECT (wbcg_get_entry (wbcg)),
		"notify::cursor-position",
		G_CALLBACK (cb_entry_cursor_pos), wbcg);
	wbcg->edit_line.signal_selection_bound = g_signal_connect_swapped (
		G_OBJECT (wbcg_get_entry (wbcg)),
		"notify::selection-bound",
		G_CALLBACK (cb_entry_cursor_pos), wbcg);

	g_free (text);
	wb_control_update_action_sensitivity (GNM_WBC (wbcg));

	wbcg->inside_editing = FALSE;

	gtk_editable_set_position (GTK_EDITABLE (wbcg_get_entry (wbcg)), cursor_pos);

	return TRUE;
}
Exemplo n.º 23
0
/**
 * gsdl_tokenizer_next:
 * @self: A valid %GSDLTokenizer.
 * @result: (out callee-allocates): A %GSDLToken to initialize and fill in.
 * @err: (out) (allow-none): Location to store any error, may be %NULL.
 *
 * Fetches the next token from the input. Depending on the source of input, may set an error in one
 * of the %GSDL_SYNTAX_ERROR, %G_IO_CHANNEL_ERROR, or %G_CONVERT_ERROR domains.
 *
 * Returns: Whether a token could be successfully read.
 */
bool gsdl_tokenizer_next(GSDLTokenizer *self, GSDLToken **result, GError **err) {
	gunichar c, nc;
	int line;
	int col;

	retry:
	line = self->line;
	col = self->col;
	if (!_read(self, &c, err)) return false;

	if (G_UNLIKELY(c == EOF)) {
		*result = _maketoken(T_EOF, line, col);
		return true;
	} else if (c == '\r') {
		if (_peek(self, &c, err) && c == '\n') _consume(self);

		*result = _maketoken('\n', line, col);
		FAIL_IF_ERR();

		return true;
	} else if ((c == '/' && _peek(self, &nc, err) && nc == '/') || (c == '-' && _peek(self, &nc, err) && nc == '-') || c == '#') {
		if (c != '#') _consume(self);
		while (_peek(self, &c, err) && !(c == '\n' || c == EOF)) _consume(self);

		goto retry;
	} else if (c == '/' && _peek(self, &nc, err) && nc == '*') {
		while (_read(self, &c, err)) {
			if (c == EOF) {
				_set_error(err,
					self,
					GSDL_SYNTAX_ERROR_UNEXPECTED_CHAR,
					"Unterminated comment"
				);

				return false;
			} else if (c == '*' && _peek(self, &c, err) && c == '/') {
				_consume(self);
				break;
			}
		}

		goto retry;
	} else if (c < 256 && strchr("-+:;./{}=\n", (char) c)) {
		*result = _maketoken(c, line, col);
		return true;
	} else if (c < 256 && isdigit((char) c)) {
		*result = _maketoken(T_NUMBER, line, col);
		return _tokenize_number(self, *result, c, err);
	} else if (g_unichar_isalpha(c) || g_unichar_type(c) == G_UNICODE_CONNECT_PUNCTUATION || g_unichar_type(c) == G_UNICODE_CURRENCY_SYMBOL) {
		*result = _maketoken(T_IDENTIFIER, line, col);
		return _tokenize_identifier(self, *result, c, err);
	} else if (c == '[') {
		*result = _maketoken(T_BINARY, line, col);
		if (!_tokenize_binary(self, *result, err)) return false;

		REQUIRE(_read(self, &c, err));
		if (c == ']') {
			return true;
		} else {
			_set_error(err,
				self,
				GSDL_SYNTAX_ERROR_MISSING_DELIMITER,
				"Missing ']'"
			);
			return false;
		}
	} else if (c == '"') {
		*result = _maketoken(T_STRING, line, col);
		if (!_tokenize_string(self, *result, err)) return false;

		REQUIRE(_read(self, &c, err));
		if (c == '"') {
			return true;
		} else {
			_set_error(err,
				self,
				GSDL_SYNTAX_ERROR_MISSING_DELIMITER,
				"Missing '\"'"
			);
			return false;
		}
	} else if (c == '`') {
		*result = _maketoken(T_STRING, line, col);
		if (!_tokenize_backquote_string(self, *result, err)) return false;

		REQUIRE(_read(self, &c, err));
		if (c == '`') {
			return true;
		} else {
			_set_error(err,
				self,
				GSDL_SYNTAX_ERROR_MISSING_DELIMITER,
				"Missing '`'"
			);
			return false;
		}
	} else if (c == '\'') {
		*result = _maketoken(T_CHAR, line, col);
		(*result)->val = g_malloc0(4);

		_read(self, &c, err);

		if (c == '\\') {
			_read(self, &c, err);

			switch (c) {
				case 'n': c = '\n'; break;
				case 'r': c = '\r'; break;
				case 't': c = '\t'; break;
				case '"': c = '"'; break;
				case '\'': c = '\''; break;
				case '\\': c = '\\'; break;
			}
		}

		g_unichar_to_utf8(c, (*result)->val); 

		REQUIRE(_read(self, &c, err));
		if (c == '\'') {
			return true;
		} else {
			_set_error(err,
				self,
				GSDL_SYNTAX_ERROR_MISSING_DELIMITER,
				"Missing \"'\""
			);
			return false;
		}
	} else if (c == '\\' && _peek(self, &nc, err) && (nc == '\r' || nc == '\n')) {
		_consume(self);

		if (c == '\r') _read(self, &c, err);

		goto retry;
	} else if (c == ' ' || c == '\t') {
		// Do nothing
		goto retry;
	} else {
		_set_error(err,
			self,
			GSDL_SYNTAX_ERROR_UNEXPECTED_CHAR,
		   	g_strdup_printf("Invalid character '%s'(%d)", g_ucs4_to_utf8(&c, 1, NULL, NULL, NULL), c)
		);
		return false;
	}
}
Exemplo n.º 24
0
gint
planner_parse_duration_with_day_length (const gchar *input,
					gint         day_length)
{
	gchar   *str;
	gchar   *p;
	gchar   *end_ptr;
	gdouble  dbl;
	Unit     unit;
	gint     total;
	gint     seconds_per_month;
	gint     seconds_per_week;

	/* Hardcode these for now. */
	seconds_per_week = day_length * 5;
	seconds_per_month = day_length * 30;

	str = g_utf8_casefold (input, -1);
	if (!str) {
		return 0;
	}

	total = 0;
	p = str;
	while (*p) {
		while (*p && g_unichar_isalpha (g_utf8_get_char (p))) {
			p = g_utf8_next_char (p);
		}

		if (*p == 0) {
			break;
		}

		dbl = g_strtod (p, &end_ptr);
		if (end_ptr == p) {
			break;
		}

		if (end_ptr) {
			unit = format_get_unit_from_string (end_ptr);

			/* If no unit was specified and it was the first number
			 * in the input, treat it as "day".
			 */
			if (unit == UNIT_NONE && p == str) {
				unit = UNIT_DAY;
			}

			total += format_multiply_with_unit (dbl,
							    unit,
							    seconds_per_month,
							    seconds_per_week,
							    day_length);
		}

		if (end_ptr && *end_ptr == 0) {
			break;
		}

		p = end_ptr + 1;
	}

	g_free (str);

	return total;
}
Exemplo n.º 25
0
static gboolean
check_part (struct mime_text_part *part, gboolean raw_mode)
{
	guchar *p, *p1;
	gunichar c, t;
	GUnicodeScript scc, sct;
	guint32 mark = 0, total = 0, max = 0, i;
	guint32 remain = part->content->len;
	guint32 scripts[G_UNICODE_SCRIPT_NKO];
	GUnicodeScript sel = 0;

	p = part->content->data;

	if (IS_PART_UTF (part) || raw_mode) {
		while (remain > 1) {
			if ((g_ascii_isalpha (*p) &&
				(*(p + 1) & 0x80)) ||
				((*p & 0x80) && g_ascii_isalpha (*(p + 1)))) {
				mark++;
				total++;
			}
			/* Current and next symbols are of one class */
			else if (((*p & 0x80) &&
				(*(p + 1) & 0x80)) ||
				(g_ascii_isalpha (*p) && g_ascii_isalpha (*(p + 1)))) {
				total++;
			}
			p++;
			remain--;
		}
	}
	else {
		memset (&scripts, 0, sizeof (scripts));
		while (remain > 0) {
			c = g_utf8_get_char_validated (p, remain);
			if (c == (gunichar) - 2 || c == (gunichar) - 1) {
				/* Invalid characters detected, stop processing */
				return FALSE;
			}

			scc = g_unichar_get_script (c);
			if (scc < (gint)G_N_ELEMENTS (scripts)) {
				scripts[scc]++;
			}
			p1 = g_utf8_next_char (p);
			remain -= p1 - p;
			p = p1;

			if (remain > 0) {
				t = g_utf8_get_char_validated (p, remain);
				if (t == (gunichar) - 2 || t == (gunichar) - 1) {
					/* Invalid characters detected, stop processing */
					return FALSE;
				}
				sct = g_unichar_get_script (t);
				if (g_unichar_isalpha (c) && g_unichar_isalpha (t)) {
					/* We have two unicode alphanumeric characters, so we can check its script */
					if (sct != scc) {
						mark++;
					}
					total++;
				}
				p1 = g_utf8_next_char (p);
				remain -= p1 - p;
				p = p1;
			}
		}
		/* Detect the mostly charset of this part */
		for (i = 0; i < G_N_ELEMENTS (scripts); i++) {
			if (scripts[i] > max) {
				max = scripts[i];
				sel = i;
			}
		}
		part->script = sel;
	}

	if (total == 0) {
		return 0;
	}

	return ((double)mark / (double)total) > chartable_module_ctx->threshold;
}
Exemplo n.º 26
0
/**
 * e_text_to_html_full:
 * @input: a NUL-terminated input buffer
 * @flags: some combination of the E_TEXT_TO_HTML_* flags defined
 * in e-html-utils.h
 * @color: color for citation highlighting
 *
 * This takes a buffer of text as input and produces a buffer of
 * "equivalent" HTML, subject to certain transformation rules.
 *
 * The set of possible flags is:
 *
 *   - E_TEXT_TO_HTML_PRE: wrap the output HTML in &lt;PRE&gt; and
 *     &lt;/PRE&gt;  Should only be used if @input is the entire
 *     buffer to be converted. If e_text_to_html is being called with
 *     small pieces of data, you should wrap the entire result in
 *     &lt;PRE&gt; yourself.
 *
 *   - E_TEXT_TO_HTML_CONVERT_NL: convert "\n" to "&lt;BR&gt;n" on
 *     output.  (Should not be used with E_TEXT_TO_HTML_PRE, since
 *     that would result in double-newlines.)
 *
 *   - E_TEXT_TO_HTML_CONVERT_SPACES: convert a block of N spaces
 *     into N-1 non-breaking spaces and one normal space. A space
 *     at the start of the buffer is always converted to a
 *     non-breaking space, regardless of the following character,
 *     which probably means you don't want to use this flag on
 *     pieces of data that aren't delimited by at least line breaks.
 *
 *     If E_TEXT_TO_HTML_CONVERT_NL and E_TEXT_TO_HTML_CONVERT_SPACES
 *     are both defined, then TABs will also be converted to spaces.
 *
 *   - E_TEXT_TO_HTML_CONVERT_URLS: wrap &lt;a href="..."&gt; &lt;/a&gt;
 *     around strings that look like URLs.
 *
 *   - E_TEXT_TO_HTML_CONVERT_ADDRESSES: wrap &lt;a href="mailto:..."&gt;
 *     &lt;/a&gt; around strings that look like mail addresses.
 *
 *   - E_TEXT_TO_HTML_MARK_CITATION: wrap &lt;font color="..."&gt;
 *     &lt;/font&gt; around citations (lines beginning with "> ", etc).
 *
 *   - E_TEXT_TO_HTML_ESCAPE_8BIT: flatten everything to US-ASCII
 *
 *   - E_TEXT_TO_HTML_CITE: quote the text with "> " at the start of each
 *     line.
 *
 * Returns: a newly-allocated string containing HTML
 **/
gchar *
e_text_to_html_full (const gchar *input,
                     guint flags,
                     guint32 color)
{
	const guchar *cur, *next, *linestart;
	gchar *buffer = NULL;
	gchar *out = NULL;
	gint buffer_size = 0, col;
	gboolean colored = FALSE, saw_citation = FALSE;

	/* Allocate a translation buffer.  */
	buffer_size = strlen (input) * 2 + 5;
	buffer = g_malloc (buffer_size);

	out = buffer;
	if (flags & E_TEXT_TO_HTML_PRE)
		out += sprintf (out, "<PRE>");

	col = 0;

	for (cur = linestart = (const guchar *) input; cur && *cur; cur = next) {
		gunichar u;

		if (flags & E_TEXT_TO_HTML_MARK_CITATION && col == 0) {
			saw_citation = is_citation (cur, saw_citation);
			if (saw_citation) {
				if (!colored) {
					gchar font[25];

					g_snprintf (font, 25, "<FONT COLOR=\"#%06x\">", color);

					out = check_size (&buffer, &buffer_size, out, 25);
					out += sprintf (out, "%s", font);
					colored = TRUE;
				}
			} else if (colored) {
				const gchar *no_font = "</FONT>";

				out = check_size (&buffer, &buffer_size, out, 9);
				out += sprintf (out, "%s", no_font);
				colored = FALSE;
			}

			/* Display mbox-mangled ">From" as "From" */
			if (*cur == '>' && !saw_citation)
				cur++;
		} else if (flags & E_TEXT_TO_HTML_CITE && col == 0) {
			out = check_size (&buffer, &buffer_size, out, 5);
			out += sprintf (out, "&gt; ");
		}

		u = g_utf8_get_char ((gchar *) cur);
		if (g_unichar_isalpha (u) &&
		    (flags & E_TEXT_TO_HTML_CONVERT_URLS)) {
			gchar *tmpurl = NULL, *refurl = NULL, *dispurl = NULL;

			if (!g_ascii_strncasecmp ((gchar *)cur, "http://", 7) ||
			    !g_ascii_strncasecmp ((gchar *)cur, "https://", 8) ||
			    !g_ascii_strncasecmp ((gchar *)cur, "ftp://", 6) ||
			    !g_ascii_strncasecmp ((gchar *)cur, "nntp://", 7) ||
			    !g_ascii_strncasecmp ((gchar *)cur, "mailto:", 7) ||
			    !g_ascii_strncasecmp ((gchar *)cur, "news:", 5) ||
			    !g_ascii_strncasecmp ((gchar *)cur, "file:", 5) ||
			    !g_ascii_strncasecmp ((gchar *)cur, "callto:", 7) ||
			    !g_ascii_strncasecmp ((gchar *)cur, "h323:", 5) ||
			    !g_ascii_strncasecmp ((gchar *)cur, "sip:", 4) ||
			    !g_ascii_strncasecmp ((gchar *)cur, "webcal:", 7)) {
				tmpurl = url_extract (&cur, TRUE);
				if (tmpurl) {
					refurl = e_text_to_html (tmpurl, 0);
					dispurl = g_strdup (refurl);
				}
			} else if (!g_ascii_strncasecmp ((gchar *)cur, "www.", 4) &&
				   is_url_char (*(cur + 4))) {
				tmpurl = url_extract (&cur, FALSE);
				if (tmpurl) {
					dispurl = e_text_to_html (tmpurl, 0);
					refurl = g_strdup_printf ("http://%s",
								  dispurl);
				}
			}

			if (tmpurl) {
				out = check_size (&buffer, &buffer_size, out,
						  strlen (refurl) +
						  strlen (dispurl) + 15);
				out += sprintf (out,
						"<a href=\"%s\">%s</a>",
						refurl, dispurl);
				col += strlen (tmpurl);
				g_free (tmpurl);
				g_free (refurl);
				g_free (dispurl);
			}

			if (!*cur)
				break;
			u = g_utf8_get_char ((gchar *) cur);
		}

		if (u == '@' && (flags & E_TEXT_TO_HTML_CONVERT_ADDRESSES)) {
			gchar *addr, *dispaddr, *outaddr;

			addr = email_address_extract (&cur, &out, linestart);
			if (addr) {
				dispaddr = e_text_to_html (addr, 0);
				outaddr = g_strdup_printf ("<a href=\"mailto:%s\">%s</a>",
							   addr, dispaddr);
				out = check_size (&buffer, &buffer_size, out, strlen (outaddr));
				out += sprintf (out, "%s", outaddr);
				col += strlen (addr);
				g_free (addr);
				g_free (dispaddr);
				g_free (outaddr);

				if (!*cur)
					break;
				u = g_utf8_get_char ((gchar *) cur);
			}
		}

		if (!g_unichar_validate (u)) {
			/* Sigh. Someone sent undeclared 8-bit data.
			 * Assume it's iso-8859-1.
			 */
			u = *cur;
			next = cur + 1;
		} else
			next = (const guchar *) g_utf8_next_char (cur);

		out = check_size (&buffer, &buffer_size, out, 10);

		switch (u) {
		case '<':
			strcpy (out, "&lt;");
			out += 4;
			col++;
			break;

		case '>':
			strcpy (out, "&gt;");
			out += 4;
			col++;
			break;

		case '&':
			strcpy (out, "&amp;");
			out += 5;
			col++;
			break;

		case '"':
			strcpy (out, "&quot;");
			out += 6;
			col++;
			break;

		case '\n':
			if (flags & E_TEXT_TO_HTML_CONVERT_NL) {
				strcpy (out, "<br>");
				out += 4;
			}
			*out++ = *cur;
			linestart = cur;
			col = 0;
			break;

		case '\t':
			if (flags & (E_TEXT_TO_HTML_CONVERT_SPACES |
				     E_TEXT_TO_HTML_CONVERT_NL)) {
				do {
					out = check_size (&buffer, &buffer_size,
						    out, 7);
					strcpy (out, "&nbsp;");
					out += 6;
					col++;
				} while (col % 8);
				break;
			}
			/* otherwise, FALL THROUGH */

		case ' ':
			if (flags & E_TEXT_TO_HTML_CONVERT_SPACES) {
				if (cur == (const guchar *) input ||
				    *(cur + 1) == ' ' || *(cur + 1) == '\t' ||
				    *(cur - 1) == '\n') {
					strcpy (out, "&nbsp;");
					out += 6;
					col++;
					break;
				}
			}
			/* otherwise, FALL THROUGH */

		default:
			if ((u >= 0x20 && u < 0x80) ||
			    (u == '\r' || u == '\t')) {
				/* Default case, just copy. */
				*out++ = u;
			} else {
				if (flags & E_TEXT_TO_HTML_ESCAPE_8BIT)
					*out++ = '?';
				else
					out += g_snprintf(out, 9, "&#%d;", u);
			}
			col++;
			break;
		}
	}

	out = check_size (&buffer, &buffer_size, out, 7);
	if (flags & E_TEXT_TO_HTML_PRE)
		strcpy (out, "</PRE>");
	else
		*out = '\0';

	return buffer;
}