コード例 #1
0
ファイル: gutf8.c プロジェクト: patito/glib
/**
 * g_utf8_to_utf16:
 * @str: a UTF-8 encoded string
 * @len: the maximum length (number of bytes) of @str to use.
 *     If @len < 0, then the string is nul-terminated.
 * @items_read: (allow-none): location to store number of bytes read,
 *     or %NULL. If %NULL, then %G_CONVERT_ERROR_PARTIAL_INPUT will be
 *     returned in case @str contains a trailing partial character. If
 *     an error occurs then the index of the invalid input is stored here.
 * @items_written: (allow-none): location to store number of #gunichar2
 *     written, or %NULL. The value stored here does not include the
 *     trailing 0.
 * @error: location to store the error occurring, or %NULL to ignore
 *     errors. Any of the errors in #GConvertError other than
 *     %G_CONVERT_ERROR_NO_CONVERSION may occur.
 *
 * Convert a string from UTF-8 to UTF-16. A 0 character will be
 * added to the result after the converted text.
 *
 * Return value: a pointer to a newly allocated UTF-16 string.
 *     This value must be freed with g_free(). If an error occurs,
 *     %NULL will be returned and @error set.
 */
gunichar2 *
g_utf8_to_utf16 (const gchar *str,
                 glong        len,
                 glong       *items_read,
                 glong       *items_written,
                 GError     **error)
{
    gunichar2 *result = NULL;
    gint n16;
    const gchar *in;
    gint i;

    g_return_val_if_fail (str != NULL, NULL);

    in = str;
    n16 = 0;
    while ((len < 0 || str + len - in > 0) && *in)
    {
        gunichar wc = g_utf8_get_char_extended (in, len < 0 ? 6 : str + len - in);
        if (wc & 0x80000000)
        {
            if (wc == (gunichar)-2)
            {
                if (items_read)
                    break;
                else
                    g_set_error_literal (error, G_CONVERT_ERROR, G_CONVERT_ERROR_PARTIAL_INPUT,
                                         _("Partial character sequence at end of input"));
            }
            else
                g_set_error_literal (error, G_CONVERT_ERROR, G_CONVERT_ERROR_ILLEGAL_SEQUENCE,
                                     _("Invalid byte sequence in conversion input"));

            goto err_out;
        }

        if (wc < 0xd800)
            n16 += 1;
        else if (wc < 0xe000)
        {
            g_set_error_literal (error, G_CONVERT_ERROR, G_CONVERT_ERROR_ILLEGAL_SEQUENCE,
                                 _("Invalid sequence in conversion input"));

            goto err_out;
        }
        else if (wc < 0x10000)
            n16 += 1;
        else if (wc < 0x110000)
            n16 += 2;
        else
        {
            g_set_error_literal (error, G_CONVERT_ERROR, G_CONVERT_ERROR_ILLEGAL_SEQUENCE,
                                 _("Character out of range for UTF-16"));

            goto err_out;
        }

        in = g_utf8_next_char (in);
    }

    result = try_malloc_n (n16 + 1, sizeof (gunichar2), error);
    if (result == NULL)
        goto err_out;

    in = str;
    for (i = 0; i < n16;)
    {
        gunichar wc = g_utf8_get_char (in);

        if (wc < 0x10000)
        {
            result[i++] = wc;
        }
        else
        {
            result[i++] = (wc - 0x10000) / 0x400 + 0xd800;
            result[i++] = (wc - 0x10000) % 0x400 + 0xdc00;
        }

        in = g_utf8_next_char (in);
    }

    result[i] = 0;

    if (items_written)
        *items_written = n16;

err_out:
    if (items_read)
        *items_read = in - str;

    return result;
}
コード例 #2
0
ファイル: testboundaries.c プロジェクト: Distrotech/pango
static void
log_attr_foreach (const char     *text,
		  PangoLogAttr   *attrs,
		  CharForeachFunc func,
		  gpointer        data)
{
  const gchar *next = text;
  gint length = strlen (text);
  const gchar *end = text + length;
  gint i = 0;
  gunichar prev_wc;
  gunichar next_wc;
  GUnicodeType prev_type;
  GUnicodeType next_type;

  if (next == end)
    return;

  offset = 0;
  line = 1;

  prev_type = (GUnicodeType) -1;
  prev_wc = 0;

  next_wc = g_utf8_get_char (next);
  next_type = g_unichar_type (next_wc);

  line_start = text;
  line_end = text;

  while (next_wc != 0)
    {
      GUnicodeType type;
      gunichar wc;

      wc = next_wc;
      type = next_type;

      current_wc = wc;

      next = g_utf8_next_char (next);
      line_end = next;

      if (next >= end)
	next_wc = 0;
      else
	next_wc = g_utf8_get_char (next);

      if (next_wc)
	next_type = g_unichar_type (next_wc);

      (* func) (wc, prev_wc, next_wc,
		type, prev_type, next_type,
		&attrs[i],
		i != 0 ? &attrs[i-1] : NULL,
		next_wc != 0 ? &attrs[i+1] : NULL,
		data);

      prev_type = type;
      prev_wc = wc;
      ++i;
      ++offset;
      if (wc == '\n')
	{
	  ++line;
	  offset = 0;
	  line_start = next;
	  line_end = next;
	}
    }
}
コード例 #3
0
ファイル: ellipsize.c プロジェクト: nihed/magnetism
/* Shapes the ellipsis using the font and is_cjk information computed by
 * update_ellipsis_shape() from the first character in the gap.
 */
static void
shape_ellipsis (EllipsizeState *state)
{
  PangoAttrList *attrs = pango_attr_list_new ();
  GSList *run_attrs;
  PangoItem *item;
  PangoGlyphString *glyphs;
  GSList *l;
  PangoAttribute *fallback;
  const char *ellipsis_text;
  int i;

  /* Create/reset state->ellipsis_run
   */
  if (!state->ellipsis_run)
    {
      state->ellipsis_run = g_slice_new (PangoGlyphItem);
      state->ellipsis_run->glyphs = pango_glyph_string_new ();
      state->ellipsis_run->item = NULL;
    }

  if (state->ellipsis_run->item)
    {
      pango_item_free (state->ellipsis_run->item);
      state->ellipsis_run->item = NULL;
    }
  
  /* Create an attribute list
   */
  run_attrs = pango_attr_iterator_get_attrs (state->gap_start_attr);
  for (l = run_attrs; l; l = l->next)
    {
      PangoAttribute *attr = l->data;
      attr->start_index = 0;
      attr->end_index = G_MAXINT;

      pango_attr_list_insert (attrs, attr);
    }

  g_slist_free (run_attrs);

  fallback = pango_attr_fallback_new (FALSE);
  fallback->start_index = 0;
  fallback->end_index = G_MAXINT;
  pango_attr_list_insert (attrs, fallback);

  /* First try using a specific ellipsis character in the best matching font
   */
  if (state->ellipsis_is_cjk)
    ellipsis_text = "\342\213\257";	/* U+22EF: MIDLINE HORIZONTAL ELLIPSIS, used for CJK */
  else
    ellipsis_text = "\342\200\246";	/* U+2026: HORIZONTAL ELLIPSIS */

  item = itemize_text (state, ellipsis_text, attrs);

  /* If that fails we use "..." in the first matching font
   */
  if (!item->analysis.font ||
      !_pango_engine_shape_covers (item->analysis.shape_engine, item->analysis.font,
				   item->analysis.language, g_utf8_get_char (ellipsis_text)))
    {
      pango_item_free (item);
      
      /* Modify the fallback iter while it is inside the PangoAttrList; Don't try this at home
       */
      ((PangoAttrInt *)fallback)->value = TRUE; 

      ellipsis_text = "...";
      item = itemize_text (state, ellipsis_text, attrs);
    }
  
  pango_attr_list_unref (attrs);
  
  state->ellipsis_run->item = item;

  /* Now shape
   */
  glyphs = state->ellipsis_run->glyphs;

  pango_shape (ellipsis_text, strlen (ellipsis_text),
	       &item->analysis, glyphs);

  state->ellipsis_width = 0;
  for (i = 0; i < glyphs->num_glyphs; i++)
    state->ellipsis_width += glyphs->glyphs[i].geometry.width;
}
コード例 #4
0
ファイル: dialog-about.c プロジェクト: paulfitz/gnumeric
static gboolean
text_item_renderer (AboutRenderer *r, AboutState *state)
{
	PangoLayout *layout = r->layout;
	int age = state->now - r->start_time;
	double rage = CLAMP (age / (double)r->duration, 0.0, 1.0);
	GtkWidget *widget = state->anim_area;
	GtkStyleContext *ctxt;
	const int fade = 500;
	int x, y, width, height;
	cairo_t *cr;
	GtkAllocation wa;
	GdkRGBA color;

	if (age >= r->duration)
		return FALSE;

	if (r->fade_in && age < fade)
		set_fade (r, state, age / (double)fade);
	else if (r->fade_out && r->duration - age < fade)
		set_fade (r, state, (r->duration - age) / (double)fade);

	ctxt = gtk_widget_get_style_context (widget);

	gtk_widget_get_allocation (widget, &wa);
	x = (int)(PANGO_SCALE * wa.width *
		  (r->start.x + rage * (r->end.x - r->start.x)));
	y = (int)(PANGO_SCALE * wa.height *
		  (r->start.y + rage * (r->end.y - r->start.y)));

	if (r->expansion.count) {
		PangoAttrList *attrlist = pango_layout_get_attributes (layout);
		const char *p, *text = pango_layout_get_text (layout);
		PangoRectangle ink, logical;

		memset (&ink, 0, sizeof (ink));
		logical = ink;

		logical.width = (int)(rage * r->expansion.rate * r->natural_width / r->expansion.count);

		p = text;
		while (*p) {
			const char *next = g_utf8_next_char (p);
			gunichar uc = g_utf8_get_char (p);
			PangoAttribute *attr;

			if (uc == UNICODE_ZERO_WIDTH_SPACE_C) {
				attr = pango_attr_shape_new (&ink, &logical);
				attr->start_index = p - text;
				attr->end_index = next - text;
				pango_attr_list_change (attrlist, attr);
			}
			p = next;
		}
		pango_layout_set_attributes (layout, attrlist);
	}

	pango_layout_get_size (layout, &width, &height);
	x -= width / 2;
	y -= height / 2;

	cr = r->cr;
	gtk_style_context_get_color (ctxt, GTK_STATE_FLAG_NORMAL, &color);
	gdk_cairo_set_source_rgba (cr, &color);
	cairo_move_to (cr, x / (double)PANGO_SCALE, y / (double)PANGO_SCALE);
	pango_cairo_show_layout (cr, layout);

	return TRUE;
}
コード例 #5
0
static void
wmem_test_strbuf(void)
{
    wmem_allocator_t   *allocator;
    wmem_strbuf_t      *strbuf;
    int                 i;

    allocator = wmem_allocator_new(WMEM_ALLOCATOR_STRICT);

    strbuf = wmem_strbuf_new(allocator, "TEST");
    g_assert(strbuf);
    g_assert_cmpstr(wmem_strbuf_get_str(strbuf), ==, "TEST");
    g_assert(wmem_strbuf_get_len(strbuf) == 4);

    wmem_strbuf_append(strbuf, "FUZZ");
    g_assert_cmpstr(wmem_strbuf_get_str(strbuf), ==, "TESTFUZZ");
    g_assert(wmem_strbuf_get_len(strbuf) == 8);

    wmem_strbuf_append_printf(strbuf, "%d%s", 3, "a");
    g_assert_cmpstr(wmem_strbuf_get_str(strbuf), ==, "TESTFUZZ3a");
    g_assert(wmem_strbuf_get_len(strbuf) == 10);

    wmem_strbuf_append_c(strbuf, 'q');
    g_assert_cmpstr(wmem_strbuf_get_str(strbuf), ==, "TESTFUZZ3aq");
    g_assert(wmem_strbuf_get_len(strbuf) == 11);

    wmem_strbuf_append_unichar(strbuf, g_utf8_get_char("\xC2\xA9"));
    g_assert_cmpstr(wmem_strbuf_get_str(strbuf), ==, "TESTFUZZ3aq\xC2\xA9");
    g_assert(wmem_strbuf_get_len(strbuf) == 13);

    wmem_strbuf_truncate(strbuf, 32);
    wmem_strbuf_truncate(strbuf, 24);
    wmem_strbuf_truncate(strbuf, 16);
    wmem_strbuf_truncate(strbuf, 13);
    g_assert_cmpstr(wmem_strbuf_get_str(strbuf), ==, "TESTFUZZ3aq\xC2\xA9");
    g_assert(wmem_strbuf_get_len(strbuf) == 13);

    wmem_strbuf_truncate(strbuf, 3);
    g_assert_cmpstr(wmem_strbuf_get_str(strbuf), ==, "TES");
    g_assert(wmem_strbuf_get_len(strbuf) == 3);

    strbuf = wmem_strbuf_sized_new(allocator, 10, 10);
    g_assert(strbuf);
    g_assert_cmpstr(wmem_strbuf_get_str(strbuf), ==, "");
    g_assert(wmem_strbuf_get_len(strbuf) == 0);

    wmem_strbuf_append(strbuf, "FUZZ");
    g_assert_cmpstr(wmem_strbuf_get_str(strbuf), ==, "FUZZ");
    g_assert(wmem_strbuf_get_len(strbuf) == 4);

    wmem_strbuf_append_printf(strbuf, "%d%s", 3, "abcdefghijklmnop");
    g_assert_cmpstr(wmem_strbuf_get_str(strbuf), ==, "FUZZ3abcd");
    g_assert(wmem_strbuf_get_len(strbuf) == 9);

    wmem_strbuf_append(strbuf, "abcdefghijklmnopqrstuvwxyz");
    g_assert_cmpstr(wmem_strbuf_get_str(strbuf), ==, "FUZZ3abcd");
    g_assert(wmem_strbuf_get_len(strbuf) == 9);

    wmem_strbuf_append_c(strbuf, 'q');
    g_assert_cmpstr(wmem_strbuf_get_str(strbuf), ==, "FUZZ3abcd");
    g_assert(wmem_strbuf_get_len(strbuf) == 9);

    wmem_strbuf_append_unichar(strbuf, g_utf8_get_char("\xC2\xA9"));
    g_assert_cmpstr(wmem_strbuf_get_str(strbuf), ==, "FUZZ3abcd");
    g_assert(wmem_strbuf_get_len(strbuf) == 9);

    wmem_free_all(allocator);

    strbuf = wmem_strbuf_new(allocator, "TEST");
    for (i=0; i<1024; i++) {
        if (g_test_rand_bit()) {
            wmem_strbuf_append(strbuf, "ABC");
        }
        else {
            wmem_strbuf_append_printf(strbuf, "%d%d", 3, 777);
        }
        wmem_strict_check_canaries(allocator);
    }
    g_assert(strlen(wmem_strbuf_get_str(strbuf)) ==
             wmem_strbuf_get_len(strbuf));

    wmem_destroy_allocator(allocator);
}
コード例 #6
0
ファイル: transliteratorm17n.c プロジェクト: ueno/libtranslit
static gchar *
transliterator_m17n_real_transliterate (TranslitTransliterator *self,
                                        const gchar            *input,
                                        guint                  *endpos,
                                        GError                **error)
{
  TransliteratorM17n *m17n = TRANSLITERATOR_M17N (self);
  const gchar *p;
  GString *string;
  gchar *output;
  gint n_filtered = 0;

  string = g_string_sized_new (strlen (input));
  minput_reset_ic (m17n->ic);
  for (p = input; ; p = g_utf8_next_char (p))
    {
      gunichar uc = g_utf8_get_char (p);
      MSymbol symbol;
      gint retval;

      if (*p == '\0')
	symbol = Mnil;
      else
	{
	  gint length;
	  gchar *utf8;

	  length = g_unichar_to_utf8 (uc, NULL);
	  utf8 = g_slice_alloc0 (length + 1);
	  g_unichar_to_utf8 (uc, utf8);
	  symbol = msymbol (utf8);
	  g_slice_free1 (length, utf8);
	}

      retval = minput_filter (m17n->ic, symbol, NULL);
      if (retval == 0)
	{
	  MText *mt = mtext ();

	  retval = minput_lookup (m17n->ic, symbol, NULL, mt);

	  if (mtext_len (mt) > 0) {
	    output = mtext_to_utf8 (mt);
	    g_string_append (string, output);
	    g_free (output);
	  }

	  if (retval)
	    g_string_append_unichar (string, uc);

	  m17n_object_unref (mt);
	  n_filtered = 0;
	}
      else
	n_filtered++;

      if (symbol == Mnil)
	break;
    }

  if (endpos)
    *endpos = g_utf8_strlen (input, -1) - n_filtered;

  return g_string_free (string, FALSE);
}
コード例 #7
0
static gboolean
emfe_text_html_format (EMailFormatterExtension *extension,
                       EMailFormatter *formatter,
                       EMailFormatterContext *context,
                       EMailPart *part,
                       GOutputStream *stream,
                       GCancellable *cancellable)
{
	if (g_cancellable_is_cancelled (cancellable))
		return FALSE;

	if (context->mode == E_MAIL_FORMATTER_MODE_RAW) {
		e_mail_formatter_format_text (
			formatter, part, stream, cancellable);

	} else if (context->mode == E_MAIL_FORMATTER_MODE_PRINTING) {
		GOutputStream *decoded_stream;
		GString *string;
		gchar *pos;
		GList *tags, *iter;
		gboolean valid;
		gchar *tag;
		const gchar *document_end;
		gpointer data;
		gsize length;
		gint i;

		decoded_stream = g_memory_output_stream_new_resizable ();

		/* FORMATTER FIXME: See above */
		e_mail_formatter_format_text (
			formatter, part, decoded_stream, cancellable);

		data = g_memory_output_stream_get_data (
			G_MEMORY_OUTPUT_STREAM (decoded_stream));
		length = g_memory_output_stream_get_data_size (
			G_MEMORY_OUTPUT_STREAM (decoded_stream));

		string = g_string_new_len ((gchar *) data, length);

		g_object_unref (decoded_stream);

		if (!g_utf8_validate (string->str, -1, NULL)) {
			gchar *valid_utf8;

			valid_utf8 = e_util_utf8_make_valid (string->str);
			g_string_free (string, TRUE);
			string = g_string_new (valid_utf8);
			g_free (valid_utf8);
		}

		tags = NULL;
		pos = string->str;
		valid = FALSE;

		do {
			gchar *tmp;
			gchar *closing;
			gchar *opening;

			tmp = g_utf8_find_next_char (pos, NULL);
			pos = g_utf8_strchr (tmp, -1, '<');
			if (!pos)
				break;

			opening = pos;
			closing = g_utf8_strchr (pos, -1, '>');

			/* Find where the actual tag name begins */
			while (tag = g_utf8_find_next_char (pos, NULL), tag != NULL) {
				gunichar c = g_utf8_get_char (tag);
				if (!g_unichar_isspace (c))
					break;
			}

			if (g_ascii_strncasecmp (tag, "style", 5) == 0) {
				tags = g_list_append (
					tags,
					get_tag (string->str, "style", opening, closing));
			} else if (g_ascii_strncasecmp (tag, "script", 6) == 0) {
				tags = g_list_append (
					tags,
					get_tag (string->str, "script", opening, closing));
			} else if (g_ascii_strncasecmp (tag, "link", 4) == 0) {
				tags = g_list_append (
					tags,
					get_tag (string->str, "link", opening, closing));
			} else if (g_ascii_strncasecmp (tag, "body", 4) == 0) {
				valid = TRUE;
				break;
			}

		} while (pos);

		/* Something's wrong, let's write the entire HTML and hope
		 * that WebKit can handle it */
		if (!valid) {
			EMailFormatterContext c = {
				.part_list = context->part_list,
				.flags = context->flags,
				.mode = E_MAIL_FORMATTER_MODE_RAW,
			};

			emfe_text_html_format (
				extension, formatter, &c,
				part, stream, cancellable);
			return FALSE;
		}

		/*	       include the "body" as well -----v */
		g_string_erase (string, 0, tag - string->str + 4);
		g_string_prepend (string, "<div ");

		for (iter = tags; iter; iter = iter->next) {
			if (iter->data)
				g_string_prepend (string, iter->data);
		}

		g_list_free_full (tags, g_free);

		document_end = NULL;
		/* We can probably use ASCII functions here */
		if (g_strrstr (string->str, "</body>")) {
			document_end = ">ydob/<";
		}

		if (g_strrstr (string->str, "</html>")) {
			if (document_end) {
				document_end = ">lmth/<>ydob/<";
			} else {
				document_end = ">lmth/<";
			}
		}

		if (document_end) {
			length = strlen (document_end);
			tag = string->str + string->len - 1;
			i = 0;
			valid = FALSE;
			while (i < length - 1) {
				gunichar c;

				c = g_utf8_get_char (tag);
				if (g_unichar_isspace (c)) {
					tag = g_utf8_find_prev_char (string->str, tag);
					continue;
				}

				c = g_unichar_tolower (c);

				if (c == document_end[i]) {
					tag = g_utf8_find_prev_char (string->str, tag);
					i++;
					valid = TRUE;
					continue;
				}

				tag = g_utf8_find_prev_char (string->str, tag);
				valid = FALSE;
			}
		} else {
			/* do not cut, if there is no end tag */
			valid = FALSE;
		}

		if (valid)
			g_string_truncate (string, tag - string->str);

		g_output_stream_write_all (
			stream, string->str, string->len,
			NULL, cancellable, NULL);

		g_string_free (string, TRUE);
	} else {
コード例 #8
0
ファイル: kanjiutils.c プロジェクト: nicolas-raoul/gjitenkai
GList* load_radkfile(GHashTable **pp_rad_info_hash, 
                     GHashTable **pp_kanji_info_hash,
                     GList      *rad_info_list) {
  int error = FALSE;
  gint rad_cnt = 0;
  gchar *radkfile_ptr;
  gchar *radkfile_end;
  RadInfo *rad_info = NULL;
  KanjiInfo *kanji_info;

  gchar *radkfile = NULL;

  GHashTable *rad_info_hash   = *pp_rad_info_hash;
  GHashTable *kanji_info_hash = *pp_kanji_info_hash;

  radkfile = read_file(RADKFILE_NAME);

  if (radkfile == NULL) gjiten_abort_with_msg("failed to read radkfile %s\n", RADKFILE_NAME);
  
  if (error == TRUE) {
    gjiten_print_error("Error opening %s.\n "                           \
                       "Check your preferences or read the documentation!",
                       RADKFILE_NAME);
    return;
  }

  radkfile_end = radkfile + strlen(radkfile); //FIXME: lseek
  radkfile_ptr = radkfile;
    
  //parse the content of the file
  while((radkfile_ptr < radkfile_end) && (radkfile_ptr != NULL)) {

    //if comment (first char on this line is #), skip this line
    if (*radkfile_ptr == '#') {  
      radkfile_ptr = get_eof_line(radkfile_ptr, radkfile_end); 
      continue;
    }
    
    //if radical info line (first char on this line is $)
    if (*radkfile_ptr == '$') {

      rad_cnt++;          //Increase number of radicals found
      radkfile_ptr = g_utf8_next_char(radkfile_ptr);

      //move the pointer forward until the character is wide (kanji)
      while (g_unichar_iswide(g_utf8_get_char(radkfile_ptr)) == FALSE) {
        radkfile_ptr = g_utf8_next_char(radkfile_ptr);
      }
      
      //new rad_info to be stored in the rad_info_hash and rad_info_list
      rad_info = g_new0(RadInfo, 1);
      rad_info->kanji_info_list = NULL;
      rad_info_list = g_list_prepend(rad_info_list, rad_info);

      //store radical character
      //the characters in the file are in UTF8 format. We need unicode.  
      gunichar utf8radical = g_utf8_get_char(radkfile_ptr);
      gunichar *p_str_radical = g_new0(gunichar, 1);
      g_unichar_to_utf8(utf8radical, (gchar*)p_str_radical);
      rad_info->radical = p_str_radical;
      
      //Find stroke number (move until digit detected)
      while (g_ascii_isdigit(*radkfile_ptr) == FALSE) {
        radkfile_ptr = g_utf8_next_char(radkfile_ptr);
      }

      //Store the stroke number
      rad_info->strokes = atoi(radkfile_ptr);  

      //insert this radical as key and the info as value
      g_hash_table_insert(rad_info_hash, (gpointer)rad_info->radical, rad_info);
      
      //Goto next line
      radkfile_ptr = get_eof_line(radkfile_ptr, radkfile_end);
    }
    else {
      //search the kanji to be stored in the list of the kanji key / radical info list
      //the kanji are located between radical $ markers and the radical info
      while ((*radkfile_ptr != '$') && (radkfile_ptr < radkfile_end)) {
        if (*radkfile_ptr == '\n') {
          radkfile_ptr++;
          continue;
        }

        gunichar utf8kanji = g_utf8_get_char(radkfile_ptr);

        gchar *kanji = g_new0(gchar, sizeof(gunichar));
        g_unichar_to_utf8(utf8kanji, kanji);
        
        //search in the kanji infohash if this kanji is alderly present, 
        //if not, create a new kanji and add it
        kanji_info = g_hash_table_lookup(kanji_info_hash, kanji);
        if (kanji_info == NULL) {
          kanji_info = g_new0(KanjiInfo, 1);
          kanji_info->rad_info_list = NULL;
          kanji_info->kanji = kanji;

          //insert this kanji as a key and the kanji info as value
          g_hash_table_insert(kanji_info_hash, (gpointer) kanji, (gpointer) kanji_info);
        }

        //add the kanji and the radical info in their respective lists
        kanji_info->rad_info_list = g_list_prepend(kanji_info->rad_info_list, rad_info);
        rad_info->kanji_info_list = g_list_prepend(rad_info->kanji_info_list, kanji_info);

        //navigate to next character
        radkfile_ptr = g_utf8_next_char(radkfile_ptr);
      }
    }
  }

  return rad_info_list;
}
コード例 #9
0
static void
e_name_western_extract_middle (ENameWestern *name,
                               ENameWesternIdxs *idxs)
{
	gchar *word;
	gchar *middle;

	/*
	 * Middle names can only exist if you have a first name.
	 */
	if (idxs->first_idx == -1)
		return;

	middle = name->full + idxs->first_idx + strlen (name->first);
	if (*middle == '\0')
		return;

	middle = g_utf8_next_char (middle);
	if (*middle == '\0')
		return;

	/*
	 * Search for the first space (or the terminating \0)
	 */
	while (g_unichar_isspace (g_utf8_get_char (middle)) &&
	       *middle != '\0')
		middle = g_utf8_next_char (middle);

	if (*middle == '\0')
		return;

	/*
	 * Skip past the nickname, if it's there.
	 */
	if (*middle == '\"') {
		if (idxs->nick_idx == -1)
			return;

		middle = name->full + idxs->nick_idx + strlen (name->nick);
		middle = g_utf8_next_char (middle);

		while (g_unichar_isspace (g_utf8_get_char (middle)) &&
		       *middle != '\0')
			middle = g_utf8_next_char (middle);

		if (*middle == '\0')
			return;
	}

	/*
	 * Make sure this isn't the beginning of a complex last name.
	 */
	word = e_name_western_get_words_at_idx (name->full, middle - name->full, 1);
	if (e_name_western_is_complex_last_beginning (word)) {
		g_free (word);
		return;
	}

	/*
	 * Make sure this isn't a suffix.
	 */
	e_name_western_cleanup_string (& word);
	if (e_name_western_word_is_suffix (word)) {
		g_free (word);
		return;
	}

	/*
	 * Make sure we didn't just grab a cute nickname.
	 */
	if (word[0] == '\"') {
		g_free (word);
		return;
	}

	idxs->middle_idx = middle - name->full;
	name->middle = word;
}
コード例 #10
0
static int
g_utf8_rangematch (const char  *pattern,
		   gunichar     test,
		   int          flags,
		   char       **new_pattern)
{
	gboolean  negate, ok;
	gunichar  c;

	/*
	 * A bracket expression starting with an unquoted circumflex
	 * character produces unspecified results (IEEE 1003.2-1992,
	 * 3.13.2).  This implementation treats it like '!', for
	 * consistency with the regular expression syntax.
	 * J.T. Conklin ([email protected])
	 */
	if ((negate = (g_utf8_get_char (pattern) == '!' || g_utf8_get_char (pattern) == '^')))
		pattern = g_utf8_next_char (pattern);

	if (flags & FNM_CASEFOLD)
		test = g_unichar_tolower (test);

	/*
	 * A right bracket shall lose its special meaning and represent
	 * itself in a bracket expression if it occurs first in the list.
	 * -- POSIX.2 2.8.3.2
	 */
	ok = FALSE;

	c = g_utf8_get_char (pattern);
	pattern = g_utf8_next_char (pattern);

	do {
		gunichar c2;

		if (c == '\\' && !(flags & FNM_NOESCAPE)) {
			c = g_utf8_get_char (pattern);
			pattern = g_utf8_next_char (pattern);
		}

		if (c == EOS)
			return (RANGE_ERROR);

		if (c == '/' && (flags & FNM_PATHNAME))
			return (RANGE_NOMATCH);

		if ((flags & FNM_CASEFOLD)) {
			c = g_unichar_tolower (c);
		}

		c2 = g_utf8_get_char (g_utf8_next_char (pattern));

		if ((g_utf8_get_char (pattern) == '-') && (c2 != EOS) && (c2 != ']')) {
			pattern = g_utf8_next_char (pattern);
			pattern = g_utf8_next_char (pattern);

			if (c2 == '\\' && !(flags & FNM_NOESCAPE)) {
				c2 = g_utf8_get_char (pattern);
				pattern = g_utf8_next_char (pattern);
			}

			if (c2 == EOS)
				return (RANGE_ERROR);

			if (flags & FNM_CASEFOLD) 
				c2 = g_unichar_tolower (c2);

			if (c <= test && test <= c2)
				ok = TRUE;

		} else if (c == test)
			ok = TRUE;

		c = g_utf8_get_char (pattern);
		pattern = g_utf8_next_char (pattern);

	} while (c != ']');
		
	*new_pattern = (char *) pattern;

	return (ok == negate ? RANGE_NOMATCH : RANGE_MATCH);
}
コード例 #11
0
static ParseResult
gimp_number_pair_entry_parse_text (GimpNumberPairEntry *entry,
                                   const gchar         *text,
                                   gdouble             *left_value,
                                   gdouble             *right_value)
{
  GimpNumberPairEntryPrivate *priv = GIMP_NUMBER_PAIR_ENTRY_GET_PRIVATE (entry);

  gdouble   new_left_number;
  gdouble   new_right_number;
  gboolean  simplify = FALSE;
  gchar    *end;

  /* try to parse a number */
  new_left_number = strtod (text, &end);

  if (end == text)
    return PARSE_CLEAR;
  else
    text = end;

  /* skip over whitespace */
  while (g_unichar_isspace (g_utf8_get_char (text)))
    text = g_utf8_next_char (text);

  /* check for a valid separator */
  if (! gimp_number_pair_entry_valid_separator (entry, g_utf8_get_char (text)))
    return PARSE_INVALID;
  else
    text = g_utf8_next_char (text);

  /* try to parse another number */
  new_right_number = strtod (text, &end);

  if (end == text)
    return PARSE_INVALID;
  else
    text = end;

  /* skip over whitespace */
  while (g_unichar_isspace (g_utf8_get_char (text)))
    text = g_utf8_next_char (text);

  /* check for the simplification char */
  if (g_utf8_get_char (text) == SIMPLIFICATION_CHAR)
    {
      simplify = priv->allow_simplification;
      text = g_utf8_next_char (text);
    }

  /* skip over whitespace */
  while (g_unichar_isspace (g_utf8_get_char (text)))
    text = g_utf8_next_char (text);

  /* check for trailing garbage */
  if (*text)
    return PARSE_INVALID;

  if (! gimp_number_pair_entry_numbers_in_range (entry,
                                                 new_left_number,
                                                 new_right_number))
    return PARSE_INVALID;

  if (simplify && new_right_number != 0.0)
    {
      gimp_number_pair_entry_ratio_to_fraction (new_left_number /
                                                new_right_number,
                                                left_value,
                                                right_value);
    }
  else
    {
      *left_value = new_left_number;
      *right_value = new_right_number;
    }

  return PARSE_VALID;
}
コード例 #12
0
int
g_utf8_fnmatch (const char *pattern, 
		const char *string, 
		int         flags)
{
	const char *stringstart;
	char       *new_pattern;
	gunichar    c, test;

	for (stringstart = string;;) {
		const char *string_1;
		gunichar    c2;

		c = g_utf8_get_char (pattern);
		pattern = g_utf8_next_char (pattern);

		switch (c) {
		case EOS:
			if ((flags & FNM_LEADING_DIR) && g_utf8_get_char (string) == '/') 
				return 0;
			return (g_utf8_get_char (string) == EOS ? 0 : FNM_NOMATCH);

		case '?':
			if (g_utf8_get_char (string) == EOS)
				return FNM_NOMATCH;

			if (g_utf8_get_char (string) == '/' && (flags & FNM_PATHNAME))
				return FNM_NOMATCH;

			string_1 = g_utf8_prev_char (string);
			if ((g_utf8_get_char (string) == '.') 
			    && (flags & FNM_PERIOD) 
			    && (string == stringstart ||
				((flags & FNM_PATHNAME) && g_utf8_get_char (string_1) == '/')))
				return FNM_NOMATCH;
			string = g_utf8_next_char (string);
			break;

		case '*':
			c = g_utf8_get_char (pattern);
			/* Collapse multiple stars. */
			while (c == '*') {
				pattern = g_utf8_next_char (pattern);
				c = g_utf8_get_char (pattern);
			}

			string_1 = g_utf8_prev_char (string);
			if ((g_utf8_get_char (string) == '.') 
			    && (flags & FNM_PERIOD) 
			    && (string == stringstart ||
				((flags & FNM_PATHNAME) && g_utf8_get_char (string_1) == '/')))
				return FNM_NOMATCH;

			/* Optimize for pattern with * at end or before /. */
			if (c == EOS) {
				if (flags & FNM_PATHNAME)
					return ((flags & FNM_LEADING_DIR) 
						|| (g_utf8_strchr (string, -1, '/') == NULL) ? 0 : FNM_NOMATCH);
				else
					return 0;

			} else if (c == '/' && (flags & FNM_PATHNAME)) {
				if ((string = g_utf8_strchr (string, -1, '/')) == NULL)
					return FNM_NOMATCH;
				break;
			}

			/* General case, use recursion. */
			while ((test = g_utf8_get_char (string)) != EOS) {
				if (! g_utf8_fnmatch (pattern, string, flags & ~FNM_PERIOD))
					return 0;
				if (test == '/' && (flags & FNM_PATHNAME))
					break;
				string = g_utf8_next_char (string);
			}
			return FNM_NOMATCH;

		case '[':
			if (g_utf8_get_char (string) == EOS)
				return FNM_NOMATCH;

			if (g_utf8_get_char (string) == '/' && (flags & FNM_PATHNAME))
				return FNM_NOMATCH;

			string_1 = g_utf8_prev_char (string);
			if ((g_utf8_get_char (string) == '.') 
			    && (flags & FNM_PERIOD) 
			    && (string == stringstart ||
				((flags & FNM_PATHNAME) && g_utf8_get_char (string_1) == '/')))
				return FNM_NOMATCH;

			switch (g_utf8_rangematch (pattern, g_utf8_get_char (string), flags, &new_pattern)) {
			case RANGE_ERROR:
				/* not a good range, treat as normal text */
				goto normal;
			case RANGE_MATCH:
				pattern = new_pattern;
				break;
			case RANGE_NOMATCH:
				return FNM_NOMATCH;
			}
			string = g_utf8_next_char (string);
			break;

		case '\\':
			if (!(flags & FNM_NOESCAPE)) {
				pattern = g_utf8_next_char (pattern);
				c = g_utf8_get_char (pattern);
				if (c == EOS) {
					c = '\\';
					pattern = g_utf8_prev_char (pattern);
				}
			}

			/* FALLTHROUGH */
		default:
		normal:
			c2 = g_utf8_get_char (string);

			if (flags & FNM_CASEFOLD) {
				c = g_unichar_tolower (c);
				c2 = g_unichar_tolower (c2);
			}

			if (c != c2)
				return FNM_NOMATCH;

			string = g_utf8_next_char (string);
			break;
		}
	}
	/* NOTREACHED */
}
コード例 #13
0
static gchar*
thunar_sbr_replace_renamer_pcre_exec (ThunarSbrReplaceRenamer *replace_renamer,
                                      const gchar             *subject)
{
  const gchar *r;
  GString     *result;
  gint         second;
  gint         first;
  gint         index;
  gint        *ovec;
  gint         olen;
  gint         rc;

  /* guess an initial ovec size */
  olen = (replace_renamer->pcre_capture_count + 10) * 3;
  ovec = g_new0 (gint, olen);

  /* try to match the subject (increasing ovec on-demand) */
  for (rc = 0; rc <= 0; )
    {
      /* try to exec, will return 0 if the ovec is too small */
      rc = pcre_exec (replace_renamer->pcre_pattern, NULL, subject, strlen (subject), 0, PCRE_NOTEMPTY, ovec, olen);
      if (G_UNLIKELY (rc < 0))
        {
          /* no match or error */
          g_free (ovec);
          return g_strdup (subject);
        }
      else if (rc == 0)
        {
          /* ovec too small, try to increase */
          olen += 18;
          ovec = g_realloc (ovec, olen * sizeof (gint));
        }
    }

  /* allocate a string for the result */
  result = g_string_sized_new (32);

  /* append the text before the match */
  g_string_append_len (result, subject, ovec[0]);

  /* apply the replacement */
  for (r = replace_renamer->replacement; *r != '\0'; r = g_utf8_next_char (r))
    {
      if (G_UNLIKELY ((r[0] == '\\' || r[0] == '$') && r[1] != '\0'))
        {
          /* skip the first char ($ or \) */
          r += 1;

          /* default to no subst */
          first = 0;
          second = 0;

          /* check the char after the \ or $ */
          if (r[0] == '+' && rc > 1)
            {
              /* \+ and $+ is replaced with the last subpattern */
              first = ovec[(rc - 1) * 2];
              second = ovec[(rc - 1) * 2 + 1];
            }
          else if (r[0] == '&')
            {
              /* \& and $& is replaced with the first subpattern (the whole match) */
              first = ovec[0];
              second = ovec[1];
            }
          else if (r[0] == '`')
            {
              /* \` and $` is replaced with the text before the whole match */
              first = 0;
              second = ovec[0];
            }
          else if (r[0] == '\'')
            {
              /* \' and $' is replaced with the text after the whole match */
              first = ovec[1];
              second = strlen (subject) - 1;
            }
          else if (g_ascii_isdigit (r[0]))
            {
              /* \<num> and $<num> is replaced with the <num>th subpattern */
              index = (r[0] - '0');
              if (G_LIKELY (index >= 0 && index < rc))
                {
                  first = ovec[2 * index];
                  second = ovec[2 * index + 1];
                }
            }
          else if (r[-1] == r[0])
            {
              /* just add the $ or \ char */
              g_string_append_c (result, r[0]);
              continue;
            }
          else
            {
              /* just ignore the $ or \ char */
              continue;
            }

          /* substitute the string */
          g_string_append_len (result, subject + first, second - first);
        }
      else
        {
          /* just append the unichar */
          g_string_append_unichar (result, g_utf8_get_char (r));
        }
    }

  /* append the text after the match */
  g_string_append (result, subject + ovec[1]);

  /* release the output vector */
  g_free (ovec);

  /* return the new name */
  return g_string_free (result, FALSE);
}
コード例 #14
0
ファイル: key.c プロジェクト: Akulen/awesome
static void
luaA_keystore(lua_State *L, int ud, const char *str, ssize_t len)
{
    if(len <= 0 || !str)
        return;

    keyb_t *key = luaA_checkudata(L, ud, &key_class);

    if(len == 1)
    {
        key->keycode = 0;
        key->keysym = str[0];
    }
    else if(str[0] == '#')
    {
        key->keycode = atoi(str + 1);
        key->keysym = 0;
    }
    else
    {
        key->keycode = 0;

        if((key->keysym = XStringToKeysym(str)) == NoSymbol )
        {
            glong length;
            gunichar unicode;

            if(!g_utf8_validate(str, -1, NULL))
            {
                luaA_warn(L, "failed to convert \"%s\" into keysym (invalid UTF-8 string)", str);
                return;
            }

            length = g_utf8_strlen(str, -1); /* This function counts combining characters. */
            if(length <= 0)
            {
                luaA_warn(L, "failed to convert \"%s\" into keysym (empty UTF-8 string)", str);
                return;
            }
            else if(length > 1)
            {
                gchar *composed = g_utf8_normalize(str, -1, G_NORMALIZE_DEFAULT_COMPOSE);
                if(g_utf8_strlen(composed, -1) != 1)
                {
                    p_delete(&composed);
                    luaA_warn(L, "failed to convert \"%s\" into keysym (failed to compose a single character)", str);
                    return;
                }
                unicode = g_utf8_get_char(composed);
                p_delete(&composed);
            }
            else
                unicode = g_utf8_get_char(str);

            if(unicode == (gunichar)-1 || unicode == (gunichar)-2)
            {
                luaA_warn(L, "failed to convert \"%s\" into keysym (neither keysym nor single unicode)", str);
                return;
            }

            /* Unicode-to-Keysym Conversion
             *
             * http://www.x.org/releases/X11R7.7/doc/xproto/x11protocol.html#keysym_encoding
             */
            if(unicode <= 0x0ff)
                key->keysym = unicode;
            else if(unicode >= 0x100 && unicode <= 0x10ffff)
                key->keysym = unicode | (1 << 24);
            else
            {
                luaA_warn(L, "failed to convert \"%s\" into keysym (unicode out of range): \"%u\"", str, unicode);
                return;
            }
        }
    }

    luaA_object_emit_signal(L, ud, "property::key", 0);
}
コード例 #15
0
static gboolean
csv_tsv_probe (GOFileOpener const *fo, GsfInput *input, GOFileProbeLevel pl)
{
	/* Rough and ready heuristic.  If the first N bytes have no
	 * unprintable characters this may be text */
	const gsf_off_t N = 512;

	if (pl == GO_FILE_PROBE_CONTENT) {
		guint8 const *header;
		gsf_off_t i;
		char const *enc = NULL;
		GString *header_utf8;
		char const *p;
		gboolean ok = TRUE;

		if (gsf_input_seek (input, 0, G_SEEK_SET))
			return FALSE;
		i = gsf_input_remaining (input);

		/* If someone ships us an empty file, accept it only if
		   it has a proper name.  */
		if (i == 0)
			return csv_tsv_probe (fo, input, GO_FILE_PROBE_FILE_NAME);

		if (i > N) i = N;
		if (NULL == (header = gsf_input_read (input, i, NULL)))
			return FALSE;

		enc = go_guess_encoding (header, i, NULL, &header_utf8, NULL);
		if (!enc)
			return FALSE;

		for (p = header_utf8->str; *p; p = g_utf8_next_char (p)) {
			gunichar uc = g_utf8_get_char (p);
			/* isprint might not be true for these: */
			if (uc == '\n' || uc == '\t' || uc == '\r')
				continue;
			/* Also, ignore a byte-order mark which may be used to
			 * indicate UTF-8; see
			 * http://en.wikipedia.org/wiki/Byte_Order_Mark for
			 * background.
			 */
			if (p == header_utf8->str && uc == 0x0000FEFF) {
				continue;
			}
			if (!g_unichar_isprint (uc)) {
				ok = FALSE;
				break;
			}
		}

		g_string_free (header_utf8, TRUE);
		return ok;
	} else {
		char const *name = gsf_input_name (input);
		if (name == NULL)
			return FALSE;
		name = gsf_extension_pointer (name);
		return (name != NULL &&
			(g_ascii_strcasecmp (name, "csv") == 0 ||
			 g_ascii_strcasecmp (name, "tsv") == 0 ||
			 g_ascii_strcasecmp (name, "txt") == 0));
	}
}
コード例 #16
0
static void
e_name_western_extract_last (ENameWestern *name,
                             ENameWesternIdxs *idxs)
{
	gchar *word;
	gint   idx = -1;
	gchar *last;

	idx = e_name_western_last_get_max_idx (name, idxs);

	/*
	 * In the case where there is no preceding name element, the
	 * name is either just a first name ("Nat", "John"), is a
	 * single-element name ("Cher", which we treat as a first
	 * name), or is just a last name.  The only time we can
	 * differentiate a last name alone from a single-element name
	 * or a first name alone is if it's a complex last name ("de
	 * Icaza", "van Josephsen").  So if there is no preceding name
	 * element, we check to see whether or not the first part of
	 * the name is the beginning of a complex name.  If it is,
	 * we subsume the entire string.  If we accidentally subsume
	 * the suffix, this will get fixed in the fixup routine.
	 */
	if (idx == -1) {
		word = e_name_western_get_words_at_idx (name->full, 0, 1);
		if (!e_name_western_is_complex_last_beginning (word)) {
			g_free (word);
			return;
		}

		name->last = g_strdup (name->full);
		idxs->last_idx = 0;
		return;
	}

	last = name->full + idx;

	/* Skip past the white space. */
	while (g_unichar_isspace (g_utf8_get_char (last)) && *last != '\0')
		last = g_utf8_next_char (last);

	if (*last == '\0')
		return;

	word = e_name_western_get_words_at_idx (name->full, last - name->full, 1);
	e_name_western_cleanup_string (& word);
	if (e_name_western_word_is_suffix (word)) {
		g_free (word);
		return;
	}
	g_free (word);

	/*
	 * Subsume the rest of the string into the last name.  If we
	 * accidentally include the prefix, it will get fixed later.
	 * This is the only way to handle things like "Miguel de Icaza
	 * Amozorrutia" without dropping data and forcing the user
	 * to retype it.
	 */
	name->last = g_strdup (last);
	idxs->last_idx = last - name->full;
}
コード例 #17
0
GSList *
empathy_smiley_manager_parse (EmpathySmileyManager *manager,
			      const gchar          *text)
{
	EmpathySmileyManagerPriv *priv = GET_PRIV (manager);
	EmpathySmiley            *smiley;
	SmileyManagerTree        *cur_tree = priv->tree;
	const gchar              *t;
	const gchar              *cur_str = text;
	GSList                   *smileys = NULL;

	g_return_val_if_fail (EMPATHY_IS_SMILEY_MANAGER (manager), NULL);
	g_return_val_if_fail (text != NULL, NULL);

	for (t = text; *t; t = g_utf8_next_char (t)) {
		SmileyManagerTree *child;
		gunichar           c;

		c = g_utf8_get_char (t);
		child = smiley_manager_tree_find_child (cur_tree, c);

		if (cur_tree == priv->tree) {
			if (child) {
				if (t > cur_str) {
					smiley = smiley_new (NULL,
							     g_strndup (cur_str, t - cur_str),
							     NULL);
					smileys = g_slist_prepend (smileys, smiley);
				}
				cur_str = t;
				cur_tree = child;
			}

			continue;
		}

		if (child) {
			cur_tree = child;
			continue;
		}

		smiley = smiley_new (cur_tree->pixbuf,
				     g_strndup (cur_str, t - cur_str),
				     cur_tree->path);
		smileys = g_slist_prepend (smileys, smiley);
		if (cur_tree->pixbuf) {
			cur_str = t;
			cur_tree = smiley_manager_tree_find_child (priv->tree, c);

			if (!cur_tree) {
				cur_tree = priv->tree;
			}
		} else {
			cur_str = t;
			cur_tree = priv->tree;
		}
	}

	smiley = smiley_new (cur_tree->pixbuf,
			     g_strndup (cur_str, t - cur_str),
			     cur_tree->path);
	smileys = g_slist_prepend (smileys, smiley);

	return g_slist_reverse (smileys);
}
コード例 #18
0
static void
e_name_western_reorder_asshole (ENameWestern *name,
                                ENameWesternIdxs *idxs)
{
	gchar *prefix;
	gchar *last;
	gchar *suffix;
	gchar *firstmidnick;
	gchar *newfull;

	gchar *comma;
	gchar *p;

	if (!e_name_western_detect_backwards (name, idxs))
		return;

	/*
	 * Convert
	 *    <Prefix> <Last name>, <First name> <Middle[+nick] name> <Suffix>
	 * to
	 *    <Prefix> <First name> <Middle[+nick] name> <Last name> <Suffix>
	 */

	/*
	 * Grab the prefix from the beginning.
	 */
	prefix = e_name_western_get_prefix_at_str (name->full);

	/*
	 * Everything from the end of the prefix to the comma is the
	 * last name.
	 */
	comma = g_utf8_strchr (name->full, -1, ',');
	if (comma == NULL) {
		g_free (prefix);
		return;
	}

	p = name->full + (prefix == NULL ? 0 : strlen (prefix));

	while (g_unichar_isspace (g_utf8_get_char (p)) && *p != '\0')
		p = g_utf8_next_char (p);

	/*
	 * Consider this case, "Br.Gate,Br. Gate,W". I know this is a damn
	 * random name, but, I got this from the bug report of 317411.
	 *
	 * comma = ",Br.Gate,W"
	 * prefix = "Br.Gate,Br."
	 * p = " Gate,W"
	 * comma - p < 0 and hence the crash.
	 *
	 * Actually, we don't have to put lot of intelligence in reordering such
	 * screwedup names, just return.
	 */
	if (comma - p + 1 < 1) {
		g_free (prefix);
		return;
	}

	last = g_malloc0 (comma - p + 1);
	strncpy (last, p, comma - p);

	/*
	 * Get the suffix off the end.
	 */
	suffix = e_name_western_get_suffix_at_str_end (name->full);

	/*
	 * Firstmidnick is everything from the comma to the beginning
	 * of the suffix.
	 */
	p = g_utf8_next_char (comma);

	while (g_unichar_isspace (g_utf8_get_char (p)) && *p != '\0')
		p = g_utf8_next_char (p);

	if (suffix != NULL) {
		gchar *q;

		/*
		 * Point q at the beginning of the suffix.
		 */
		q = name->full + strlen (name->full) - strlen (suffix);
		q = g_utf8_prev_char (q);

		/*
		 * Walk backwards until we hit the space which
		 * separates the suffix from firstmidnick.
		 */
		while (!g_unichar_isspace (g_utf8_get_char (q)) && q > comma)
			q = g_utf8_prev_char (q);

		if ((q - p + 1) > 0) {
			firstmidnick = g_malloc0 (q - p + 1);
			strncpy (firstmidnick, p, q - p);
		} else
			firstmidnick = NULL;
	} else {
		firstmidnick = g_strdup (p);
	}

	/*
	 * Create our new reordered version of the name.
	 */
#define NULLSTR(a) ((a) == NULL ? "" : (a))
	newfull = g_strdup_printf (
		"%s %s %s %s",
		NULLSTR (prefix),
		NULLSTR (firstmidnick),
		NULLSTR (last),
		NULLSTR (suffix));
	g_strstrip (newfull);
	g_free (name->full);
	name->full = newfull;

	g_free (prefix);
	g_free (firstmidnick);
	g_free (last);
	g_free (suffix);
}
コード例 #19
0
/**
 * clutter_gdk_handle_event:
 * @event: a #GdkEvent
 *
 * This function processes a single GDK event; it can be used to hook
 * into external event processing
 *
 * Return value: #GdkFilterReturn. %GDK_FILTER_REMOVE indicates that
 *  Clutter has internally handled the event and the caller should do
 *  no further processing. %GDK_FILTER_CONTINUE indicates that Clutter
 *  is either not interested in the event, or has used the event to
 *  update internal state without taking any exclusive action.
 *  %GDK_FILTER_TRANSLATE will not occur.
 *
 */
GdkFilterReturn
clutter_gdk_handle_event (GdkEvent *gdk_event)
{
  ClutterDeviceManager *device_manager;
  ClutterBackendGdk *backend_gdk;
  ClutterBackend *backend;
  ClutterStage *stage = NULL;
  ClutterEvent *event = NULL;
  gint spin = 0;
  GdkFilterReturn result = GDK_FILTER_CONTINUE;
  ClutterInputDevice *device, *source_device;
  GdkDevice *gdk_device;

  backend = clutter_get_default_backend ();
  if (!CLUTTER_IS_BACKEND_GDK (backend))
    return GDK_FILTER_CONTINUE;

  if (gdk_event->any.window == NULL)
    return GDK_FILTER_CONTINUE;

  device_manager = clutter_device_manager_get_default ();
  if (G_UNLIKELY (device_manager == NULL))
    return GDK_FILTER_CONTINUE;

  backend_gdk = CLUTTER_BACKEND_GDK (backend);
  stage = clutter_gdk_get_stage_from_window (gdk_event->any.window);

  gdk_device = gdk_event_get_device (gdk_event);
  if (gdk_device != NULL)
    device = _clutter_device_manager_gdk_lookup_device (device_manager,
                                                        gdk_device);
  else
    device = NULL;

  gdk_device = gdk_event_get_source_device (gdk_event);
  if (gdk_device != NULL)
    source_device = _clutter_device_manager_gdk_lookup_device (device_manager,
                                                               gdk_device);
  else
    source_device = NULL;

  if (stage == NULL)
    return GDK_FILTER_CONTINUE;

  _clutter_threads_acquire_lock ();

  switch (gdk_event->type)
    {
    case GDK_DELETE:
      event = clutter_event_new (CLUTTER_DELETE);
      break;

    case GDK_DESTROY:
      event = clutter_event_new (CLUTTER_DESTROY_NOTIFY);
      break;

    case GDK_EXPOSE:
      {
        ClutterPaintVolume clip;
        ClutterVertex origin;

        CLUTTER_NOTE (EVENT, "Expose for stage '%s' [%p] { %d, %d - %d x %d }",
                      _clutter_actor_get_debug_name (CLUTTER_ACTOR (stage)),
                      stage,
                      gdk_event->expose.area.x,
                      gdk_event->expose.area.y,
                      gdk_event->expose.area.width,
                      gdk_event->expose.area.height);

        origin.x = gdk_event->expose.area.x;
        origin.y = gdk_event->expose.area.y;
        origin.z = 0;

        _clutter_paint_volume_init_static (&clip, CLUTTER_ACTOR (stage));

        clutter_paint_volume_set_origin (&clip, &origin);
        clutter_paint_volume_set_width (&clip, gdk_event->expose.area.width);
        clutter_paint_volume_set_height (&clip, gdk_event->expose.area.height);

        _clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stage), 0, &clip);

        clutter_paint_volume_free (&clip);
      }
      break;

    case GDK_DAMAGE:
      /* This is handled by cogl */
      break;

    case GDK_MOTION_NOTIFY:
      event = clutter_event_new (CLUTTER_MOTION);
      event->motion.time = gdk_event->motion.time;
      event->motion.x = gdk_event->motion.x;
      event->motion.y = gdk_event->motion.y;
      event->motion.axes = NULL;
      /* It's all X in the end, right? */
      event->motion.modifier_state = gdk_event->motion.state;
      clutter_event_set_device (event, device);
      clutter_event_set_source_device (event, source_device);
      CLUTTER_NOTE (EVENT, "Motion notifiy [%.2f, %.2f]",
                    event->motion.x,
                    event->motion.y);
      break;

    case GDK_BUTTON_PRESS:
    case GDK_BUTTON_RELEASE:
      event = clutter_event_new (gdk_event->type == GDK_BUTTON_PRESS ?
                                 CLUTTER_BUTTON_PRESS :
                                 CLUTTER_BUTTON_RELEASE);
      event->button.time = gdk_event->button.time;
      event->button.x = gdk_event->button.x;
      event->button.y = gdk_event->button.y;
      event->button.axes = NULL;
      event->button.modifier_state = gdk_event->button.state;
      event->button.button = gdk_event->button.button;
      event->button.click_count = 1;
      clutter_event_set_device (event, device);
      clutter_event_set_source_device (event, source_device);
      CLUTTER_NOTE (EVENT, "Button %d %s [%.2f, %.2f]",
                    event->button.button,
                    event->type == CLUTTER_BUTTON_PRESS ? "press" : "release",
                    event->button.x,
                    event->button.y);
      break;

    case GDK_2BUTTON_PRESS:
    case GDK_3BUTTON_PRESS:
      /* these are handled by clutter-main.c updating click_count */
      break;

    case GDK_KEY_PRESS:
    case GDK_KEY_RELEASE:
      event = clutter_event_new (gdk_event->type == GDK_KEY_PRESS ?
                                 CLUTTER_KEY_PRESS :
                                 CLUTTER_KEY_RELEASE);
      event->key.time = gdk_event->key.time;
      event->key.modifier_state = gdk_event->key.state;
      event->key.keyval = gdk_event->key.keyval;
      event->key.hardware_keycode = gdk_event->key.hardware_keycode;
      event->key.unicode_value = g_utf8_get_char (gdk_event->key.string);
      clutter_event_set_device (event, device);
      clutter_event_set_source_device (event, source_device);
      CLUTTER_NOTE (EVENT, "Key %d %s",
                    event->key.keyval,
                    event->type == CLUTTER_KEY_PRESS ? "press" : "release");
      break;

    case GDK_ENTER_NOTIFY:
    case GDK_LEAVE_NOTIFY:
      event = clutter_event_new (gdk_event->type == GDK_ENTER_NOTIFY ?
                                 CLUTTER_ENTER :
                                 CLUTTER_LEAVE);
      event->crossing.source = CLUTTER_ACTOR (stage);
      event->crossing.time = gdk_event_get_time (gdk_event);
      event->crossing.x = gdk_event->crossing.x;
      event->crossing.y = gdk_event->crossing.y;

      /* XXX: no better fallback here? */
      clutter_event_set_device (event, device);
      clutter_event_set_source_device (event, source_device);
      if (gdk_event->type == GDK_ENTER_NOTIFY)
        _clutter_input_device_set_stage (clutter_event_get_device (event), stage);
      else
        _clutter_input_device_set_stage (clutter_event_get_device (event), NULL);
      CLUTTER_NOTE (EVENT, "Crossing %s [%.2f, %.2f]",
                    event->type == CLUTTER_ENTER ? "enter" : "leave",
                    event->crossing.x,
                    event->crossing.y);
      break;

    case GDK_FOCUS_CHANGE:
      if (gdk_event->focus_change.in)
        _clutter_stage_update_state (stage, 0, CLUTTER_STAGE_STATE_ACTIVATED);
      else
        _clutter_stage_update_state (stage, CLUTTER_STAGE_STATE_ACTIVATED, 0);
      break;

    case GDK_CONFIGURE:
      {
        gfloat w, h;

        clutter_actor_get_size (CLUTTER_ACTOR (stage), &w, &h);

        if (w != gdk_event->configure.width ||
            h != gdk_event->configure.height)
          {
            clutter_actor_set_size (CLUTTER_ACTOR (stage),
                                    gdk_event->configure.width,
                                    gdk_event->configure.height);
          }
      }
      break;

    case GDK_SCROLL:
      event = clutter_event_new (CLUTTER_SCROLL);
      event->scroll.time = gdk_event->scroll.time;
      event->scroll.x = gdk_event->scroll.x;
      event->scroll.y = gdk_event->scroll.y;
      event->scroll.modifier_state = gdk_event->scroll.state;
      event->scroll.axes = NULL;
      /* XXX: must keep ClutterScrollDirection compatible with GdkScrollDirection */
      event->scroll.direction = (ClutterScrollDirection) gdk_event->scroll.direction;
      clutter_event_set_device (event, device);
      clutter_event_set_source_device (event, source_device);
      clutter_event_set_scroll_delta (event,
                                      gdk_event->scroll.delta_x,
                                      gdk_event->scroll.delta_y);
      break;

    case GDK_WINDOW_STATE:
      if (gdk_event->window_state.changed_mask & GDK_WINDOW_STATE_FULLSCREEN)
        {
          gboolean is_fullscreen;

          is_fullscreen = (gdk_event->window_state.new_window_state & GDK_WINDOW_STATE_FULLSCREEN) != 0;
          if (is_fullscreen)
            _clutter_stage_update_state (stage, 0, CLUTTER_STAGE_STATE_FULLSCREEN);
          else
            _clutter_stage_update_state (stage, CLUTTER_STAGE_STATE_FULLSCREEN, 0);
        }
      break;

    case GDK_SETTING:
      _clutter_backend_gdk_update_setting (backend_gdk, gdk_event->setting.name);
      break;

    default:
      break;
    }

  if (event != NULL)
    {
      event->any.stage = stage;

      if (gdk_event->any.send_event)
	event->any.flags = CLUTTER_EVENT_FLAG_SYNTHETIC;

      _clutter_event_push (event, FALSE);

      spin = 1;

      CLUTTER_NOTE (EVENT, "Translated one event from Gdk");

      /* handle also synthetic enter/leave events */
      if (event->type == CLUTTER_MOTION)
	spin += 2;

      while (spin > 0 && (event = clutter_event_get ()))
	{
	  /* forward the event into clutter for emission etc. */
	  clutter_do_event (event);
	  clutter_event_free (event);
	  --spin;
	}

      result = GDK_FILTER_REMOVE;
    }

  _clutter_threads_release_lock ();

  return result;
}
コード例 #20
0
static void
e_name_western_fixup (ENameWestern *name,
                      ENameWesternIdxs *idxs)
{
	/*
	 * The middle and last names cannot be the same.
	 */
	if (idxs->middle_idx != -1 && idxs->middle_idx == idxs->last_idx) {
		idxs->middle_idx = -1;
		g_free (name->middle);
		name->middle = NULL;
	}

	/*
	 * If we have a middle name and no last name, then we mistook
	 * the last name for the middle name.
	 */
	if (idxs->last_idx == -1 && idxs->middle_idx != -1) {
		idxs->last_idx = idxs->middle_idx;
		name->last = name->middle;
		name->middle = NULL;
		idxs->middle_idx = -1;
	}

	/*
	 * Check to see if we accidentally included the suffix in the
	 * last name.
	 */
	if (idxs->suffix_idx != -1 && idxs->last_idx != -1 &&
	    idxs->suffix_idx < (idxs->last_idx + strlen (name->last))) {
		gchar *sfx;

		sfx = name->last + (idxs->suffix_idx - idxs->last_idx);
		if (sfx != NULL) {
			gchar *newlast;
			gchar *p;

			p = sfx;
			p = g_utf8_prev_char (p);
			while (g_unichar_isspace (g_utf8_get_char (p)) && p > name->last)
				p = g_utf8_prev_char (p);
			p = g_utf8_next_char (p);

			newlast = g_malloc0 (p - name->last + 1);
			strncpy (newlast, name->last, p - name->last);
			g_free (name->last);
			name->last = newlast;
		}
	}

	/*
	 * If we have a prefix and a first name, but no last name,
	 * then we need to assign the first name to the last name.
	 * This way we get things like "Mr Friedman" correctly.
	 */
	if (idxs->first_idx != -1 && idxs->prefix_idx != -1 &&
	    idxs->last_idx == -1) {
		name->last = name->first;
		idxs->last_idx = idxs->first_idx;
		idxs->first_idx = -1;
		name->first = NULL;
	}

	if (idxs->middle_idx != -1) {
		CHECK_MIDDLE_NAME_FOR_CONJUNCTION ("&");
		CHECK_MIDDLE_NAME_FOR_CONJUNCTION ("*");
		CHECK_MIDDLE_NAME_FOR_CONJUNCTION ("|");
		CHECK_MIDDLE_NAME_FOR_CONJUNCTION ("^");
		CHECK_MIDDLE_NAME_FOR_CONJUNCTION ("&&");
		CHECK_MIDDLE_NAME_FOR_CONJUNCTION ("||");
		CHECK_MIDDLE_NAME_FOR_CONJUNCTION ("+");
		CHECK_MIDDLE_NAME_FOR_CONJUNCTION ("-");
		CHECK_MIDDLE_NAME_FOR_CONJUNCTION_CASE ("and");
		CHECK_MIDDLE_NAME_FOR_CONJUNCTION_CASE ("or");
		CHECK_MIDDLE_NAME_FOR_CONJUNCTION_CASE ("plus");

		/* Spanish */
		CHECK_MIDDLE_NAME_FOR_CONJUNCTION_CASE ("y");

		/* German */
		CHECK_MIDDLE_NAME_FOR_CONJUNCTION_CASE ("und");

		/* Italian */
		CHECK_MIDDLE_NAME_FOR_CONJUNCTION_CASE ("e");

		/* Czech */
		CHECK_MIDDLE_NAME_FOR_CONJUNCTION_CASE ("a");

		/* Finnish */
		CHECK_MIDDLE_NAME_FOR_CONJUNCTION_CASE ("ja");

		/* French */
		CHECK_MIDDLE_NAME_FOR_CONJUNCTION_CASE ("et");

		/* Russian */
		CHECK_MIDDLE_NAME_FOR_CONJUNCTION ("\xd0\x98"); /* u+0418 */
		CHECK_MIDDLE_NAME_FOR_CONJUNCTION ("\xd0\xb8"); /* u+0438 */
	}

	/*
	 * Remove stray spaces and commas (although there don't seem
	 * to be any in the test cases, they might show up later).
	 */
	e_name_western_cleanup_string (& name->prefix);
	e_name_western_cleanup_string (& name->first);
	e_name_western_cleanup_string (& name->middle);
	e_name_western_cleanup_string (& name->nick);
	e_name_western_cleanup_string (& name->last);
	e_name_western_cleanup_string (& name->suffix);

	/*
	 * Make zero-length strings just NULL.
	 */
	e_name_western_zap_nil (& name->prefix, & idxs->prefix_idx);
	e_name_western_zap_nil (& name->first,  & idxs->first_idx);
	e_name_western_zap_nil (& name->middle, & idxs->middle_idx);
	e_name_western_zap_nil (& name->nick,   & idxs->nick_idx);
	e_name_western_zap_nil (& name->last,   & idxs->last_idx);
	e_name_western_zap_nil (& name->suffix, & idxs->suffix_idx);
}
コード例 #21
0
static gchar *
get_tag (const gchar *utf8_string,
         const gchar *tag_name,
         gchar *opening,
         gchar *closing)
{
	gchar *t;
	gunichar c;
	gboolean has_end;

	c = '\0';
	t = g_utf8_find_prev_char (utf8_string, closing);
	while (t != opening) {

		c = g_utf8_get_char (t);
		if (!g_unichar_isspace (c))
			break;
	}

	/* Not a pair tag */
	if (c == '/')
		return g_strndup (opening, closing - opening + 1);

	t = closing;
	while (t) {
		c = g_utf8_get_char (t);
		if (c == '<') {
			if (t[1] == '!' && t[2] == '-' && t[3] == '-') {
				/* it's a comment start, read until the end of "-->" */
				gchar *end = strstr (t + 4, "-->");
				if (end) {
					t = end + 2;
				} else
					break;
			} else
				break;
		}

		t = g_utf8_find_next_char (t, NULL);
	}

	has_end = FALSE;
	do {
		c = g_utf8_get_char (t);

		if (c == '/') {
			has_end = TRUE;
			break;
		}

		if (c == '>') {
			has_end = FALSE;
			break;
		}

		t = g_utf8_find_next_char (t, NULL);

	} while (t);

	/* Broken HTML? */
	if (!has_end)
		return NULL;

	do {
		c = g_utf8_get_char (t);
		if ((c != ' ') && (c != '/'))
			break;

		t = g_utf8_find_next_char (t, NULL);
	} while (t);

	/* tag_name is always ASCII */
	if (g_ascii_strncasecmp (t, tag_name, strlen (tag_name)) == 0) {

		closing = g_utf8_strchr (t, -1, '>');

		return g_strndup (opening, closing - opening + 1);
	}

	/* Broken HTML? */
	return NULL;
}
コード例 #22
0
ファイル: gnc-csv-model.c プロジェクト: cstim/gnucash-svn
/** Sets the value of the property by parsing str. Note: this should
 * only be called once on an instance of TransProperty, as calling it
 * more than once can cause memory leaks.
 * @param prop The property being set
 * @param str The string to be parsed
 * @return TRUE on success, FALSE on failure
 */
static gboolean trans_property_set(TransProperty* prop, char* str)
{
    char *endptr, *possible_currency_symbol, *str_dupe;
    double value;
    switch (prop->type)
    {
    case GNC_CSV_DATE:
        prop->value = g_new(time_t, 1);
        *((time_t*)(prop->value)) = parse_date(str, prop->list->date_format);
        return *((time_t*)(prop->value)) != -1;

    case GNC_CSV_DESCRIPTION:
    case GNC_CSV_NUM:
        prop->value = g_strdup(str);
        return TRUE;

    case GNC_CSV_BALANCE:
    case GNC_CSV_DEPOSIT:
    case GNC_CSV_WITHDRAWAL:
        str_dupe = g_strdup(str); /* First, we make a copy so we can't mess up real data. */

        /* Go through str_dupe looking for currency symbols. */
        for (possible_currency_symbol = str_dupe; *possible_currency_symbol;
        possible_currency_symbol = g_utf8_next_char(possible_currency_symbol))
        {
            if (g_unichar_type(g_utf8_get_char(possible_currency_symbol)) == G_UNICODE_CURRENCY_SYMBOL)
            {
                /* If we find a currency symbol, save the position just ahead
                 * of the currency symbol (next_symbol), and find the null
                 * terminator of the string (last_symbol). */
                char *next_symbol = g_utf8_next_char(possible_currency_symbol), *last_symbol = next_symbol;
                while (*last_symbol)
                    last_symbol = g_utf8_next_char(last_symbol);

                /* Move all of the string (including the null byte, which is
                 * why we have +1 in the size parameter) following the
                 * currency symbol back one character, thereby overwriting the
                 * currency symbol. */
                memmove(possible_currency_symbol, next_symbol, last_symbol - next_symbol + 1);
                break;
            }
        }

        /* Translate the string (now clean of currency symbols) into a number. */
        value = strtod(str_dupe, &endptr);

        /* If this isn't a valid numeric string, this is an error. */
        if (endptr != str_dupe + strlen(str_dupe))
        {
            g_free(str_dupe);
            return FALSE;
        }

        g_free(str_dupe);

        if (abs(value) > 0.00001)
        {
            prop->value = g_new(gnc_numeric, 1);
            *((gnc_numeric*)(prop->value)) =
            double_to_gnc_numeric(value, xaccAccountGetCommoditySCU(prop->list->account),
            GNC_RND_ROUND);
        }
        return TRUE;
    }
    return FALSE; /* We should never actually get here. */
}
コード例 #23
0
ファイル: dialog-utils.c プロジェクト: Mechtilde/gnucash
gboolean
gnc_handle_date_accelerator (GdkEventKey *event,
                             struct tm *tm,
                             const char *date_str)
{
    GDate gdate;

    g_return_val_if_fail (event != NULL, FALSE);
    g_return_val_if_fail (tm != NULL, FALSE);
    g_return_val_if_fail (date_str != NULL, FALSE);

    if (event->type != GDK_KEY_PRESS)
        return FALSE;

    if ((tm->tm_mday <= 0) || (tm->tm_mon == -1) || (tm->tm_year == -1))
        return FALSE;

    // Make sure we have a valid date before we proceed
    if (!g_date_valid_dmy (tm->tm_mday, tm->tm_mon + 1, tm->tm_year + 1900))
        return FALSE;

    g_date_set_dmy (&gdate,
                    tm->tm_mday,
                    tm->tm_mon + 1,
                    tm->tm_year + 1900);

    /*
     * Check those keys where the code does different things depending
     * upon the modifiers.
     */
    switch (event->keyval)
    {
    case GDK_KEY_KP_Add:
    case GDK_KEY_plus:
    case GDK_KEY_equal:
        if (event->state & GDK_SHIFT_MASK)
            g_date_add_days (&gdate, 7);
        else if (event->state & GDK_MOD1_MASK)
            g_date_add_months (&gdate, 1);
        else if (event->state & GDK_CONTROL_MASK)
            g_date_add_years (&gdate, 1);
        else
            g_date_add_days (&gdate, 1);
        g_date_to_struct_tm (&gdate, tm);
        return TRUE;

    case GDK_KEY_minus:
    case GDK_KEY_KP_Subtract:
    case GDK_KEY_underscore:
        if ((strlen (date_str) != 0) && (dateSeparator () == '-'))
        {
            const char *c;
            gunichar uc;
            int count = 0;

            /* rough check for existing date */
            c = date_str;
            while (*c)
            {
                uc = g_utf8_get_char (c);
                if (uc == '-')
                    count++;
                c = g_utf8_next_char (c);
            }

            if (count < 2)
                return FALSE;
        }

        if (event->state & GDK_SHIFT_MASK)
            g_date_subtract_days (&gdate, 7);
        else if (event->state & GDK_MOD1_MASK)
            g_date_subtract_months (&gdate, 1);
        else if (event->state & GDK_CONTROL_MASK)
            g_date_subtract_years (&gdate, 1);
        else
            g_date_subtract_days (&gdate, 1);
        g_date_to_struct_tm (&gdate, tm);
        return TRUE;

    default:
        break;
    }

    /*
     * Control and Alt key combinations should be ignored by this
     * routine so that the menu system gets to handle them.  This
     * prevents weird behavior of the menu accelerators (i.e. work in
     * some widgets but not others.)
     */
    if (event->state & (GDK_MODIFIER_INTENT_DEFAULT_MOD_MASK))
        return FALSE;

    /* Now check for the remaining keystrokes. */
    switch (event->keyval)
    {
    case GDK_KEY_braceright:
    case GDK_KEY_bracketright:
        /* increment month */
        g_date_add_months (&gdate, 1);
        break;

    case GDK_KEY_braceleft:
    case GDK_KEY_bracketleft:
        /* decrement month */
        g_date_subtract_months (&gdate, 1);
        break;

    case GDK_KEY_M:
    case GDK_KEY_m:
        /* beginning of month */
        g_date_set_day (&gdate, 1);
        break;

    case GDK_KEY_H:
    case GDK_KEY_h:
        /* end of month */
        g_date_set_day (&gdate, 1);
        g_date_add_months (&gdate, 1);
        g_date_subtract_days (&gdate, 1);
        break;

    case GDK_KEY_Y:
    case GDK_KEY_y:
        /* beginning of year */
        g_date_set_day (&gdate, 1);
        g_date_set_month (&gdate, 1);
        break;

    case GDK_KEY_R:
    case GDK_KEY_r:
        /* end of year */
        g_date_set_day (&gdate, 1);
        g_date_set_month (&gdate, 1);
        g_date_add_years (&gdate, 1);
        g_date_subtract_days (&gdate, 1);
        break;

    case GDK_KEY_T:
    case GDK_KEY_t:
        /* today */
        gnc_gdate_set_today (&gdate);
        break;

    default:
        return FALSE;
    }

    g_date_to_struct_tm (&gdate, tm);

    return TRUE;
}
コード例 #24
0
ファイル: TextWrapper.cpp プロジェクト: Spin0za/inkscape
void text_wrapper::AppendUTF8(char const *text, int len)
{
    // appends text to what needs to be handled
    if ( utf8_length <= 0 ) {
        // a first check to prevent the text from containing a leading line return (which
        // is probably a bug anyway)
        if ( text[0] == '\n' || text[0] == '\r' ) {
            /* fixme: Should the below be `0 <= len' ?  The existing code looks wrong
             * for the case that len==0.
             * TODO: Document the meaning of the len parameter. */
            if ( len > 0 ) {
                while ( len > 0 && ( *text == '\n' || *text == '\r' ) ) {text++; len--;}
            } else {
                while ( *text == '\n' || *text == '\r' ) text++;
            }
        }
    }
    if ( len == 0 || text == NULL || *text == 0 ) return;
    g_return_if_fail(g_utf8_validate(text, len, NULL));

    // compute the length
    int const nlen = ( len < 0
                       ? strlen(text)
                       : len );
    /* effic: Use g_utf8_validate's last param to do this. */

    // prepare to store the additional text
    /* effic: (Not an issue for the sole caller at the time of writing.)  This implementation
       takes quadratic time if the text is composed of n appends.  Use a proper data structure.
       STL vector would suffice. */
    utf8_text = (char*)realloc(utf8_text, (utf8_length + nlen + 1) * sizeof(char));
    uni32_codepoint = (int*)realloc(uni32_codepoint, (utf8_length + nlen + 1) * sizeof(int));

    // copy the source text in the newly lengthened array
    memcpy(utf8_text + utf8_length, text, nlen * sizeof(char));
    utf8_length += nlen;
    utf8_text[utf8_length] = 0;
    // remember where the text ended, before we recompute it, for the dx/dy we'll add after that (if any)
    last_addition = uni32_length;
    // free old uni32 structures (instead of incrementally putting the text)
    if ( uni32_text ) free(uni32_text);
    if ( utf8_codepoint ) free(utf8_codepoint);
    uni32_text = NULL;
    utf8_codepoint = NULL;
    uni32_length = 0;
    {
        // recompute length of uni32 text
        char *p = utf8_text;
        while ( *p ) {
            p = g_utf8_next_char(p); // since we validated the input text, we can use this 'fast' macro
            uni32_length++;
        }
    }
    // realloc the arrays
    uni32_text = (gunichar*)malloc((uni32_length + 1) * sizeof(gunichar));
    utf8_codepoint = (int*)malloc((uni32_length + 1) * sizeof(int));
    {
        // read the utf8 string and compute codepoints positions
        char *p = utf8_text;
        int i = 0;
        int l_o = 0;
        while ( *p ) {
            // get the new codepoint
            uni32_text[i] = g_utf8_get_char(p);
            // compute the offset in the utf8_string
            unsigned int n_o = (unsigned int)(p - utf8_text);
            // record the codepoint's start
            utf8_codepoint[i] = n_o;
            // record the codepoint's correspondance in the utf8 string
            for (unsigned int j = l_o; j < n_o; j++) uni32_codepoint[j] = i - 1;
            // and move on
            l_o = n_o;
            p = g_utf8_next_char(p);
            i++;
        }
        // the termination of the loop
        for (int j = l_o; j < utf8_length; j++) uni32_codepoint[j] = uni32_length - 1;
        uni32_codepoint[utf8_length] = uni32_length;
        uni32_text[uni32_length] = 0;
        utf8_codepoint[uni32_length] = utf8_length;
    }
    // if needed, fill the dx/dy arrays with 0 for the newly created part
    // these will be filled by a KernXForLastAddition() right after this function
    // note that the SVG spec doesn't require you to give a dx for each codepoint,
    // so setting the dx to 0 is mandatory
    if ( uni32_length > last_addition ) {
        if ( kern_x ) {
            kern_x = (double*)realloc(kern_x, (uni32_length + 1) * sizeof(double));
            for (int i = last_addition; i <= uni32_length; i++) kern_x[i] = 0;
        }
        if ( kern_y ) {
            kern_y = (double*)realloc(kern_y, (uni32_length + 1) * sizeof(double));
            for (int i = last_addition; i <= uni32_length; i++) kern_y[i] = 0;
        }
    }
}
コード例 #25
0
int req_parser_add_text(req_parser *r, const char *data, size_t len)
{
	const char *end;
	if (!g_utf8_validate(data, len, &end))
	{
		return REQ_PARSER_PARSE_INVALID_REQUEST;
	}

	int result = REQ_PARSER_PARSE_PARTIAL_REQUEST;

	int mode = (r->method == REQ_PARSER_METHOD_INVALID) ? MODE_REQUEST_LINE : MODE_HEADER_LINE;
	const gchar *headerQuark = NULL;

	char buf[HEADER_BUF_SIZE];
	const char *token_start = data;
	const char *i;
	for (i = data; (i < end) && *i; i = g_utf8_next_char(i))
	{
		result = REQ_PARSER_PARSE_PARTIAL_REQUEST;
		gunichar c = g_utf8_get_char(i);

		if (c == '\r')
		{
			i = g_utf8_next_char(i);
			c = g_utf8_get_char(i);
		}
		if ((c == '\n') && (*g_utf8_prev_char(i) != '\r'))
		{
			fprintf(stderr, "ERROR - Encountered a newline without a preceding carriage return.\n");
			req_parser_reset(r);
			return REQ_PARSER_PARSE_INVALID_REQUEST;
		}

		switch (mode)
		{
		case MODE_REQUEST_LINE:
			if (c == ' ')
			{
				if (r->method == REQ_PARSER_METHOD_INVALID)
				{
					if (strncmp("GET", token_start, 3) == 0) r->method = REQ_PARSER_METHOD_GET;
					else if (strncmp("HEAD", token_start, 4) == 0) r->method = REQ_PARSER_METHOD_HEAD;
					else if (strncmp("POST", token_start, 4) == 0) r->method = REQ_PARSER_METHOD_POST;
					else if (strncmp("OPTIONS", token_start, 7) == 0) r->method = REQ_PARSER_METHOD_OPTIONS;
					else
					{
						fprintf(stderr, "ERROR - Unknown method\n");
						req_parser_reset(r);
						return REQ_PARSER_PARSE_INVALID_REQUEST;
					}

					// skip over the separating space
					i = g_utf8_next_char(i);
					token_start = i;
				}
				else if (r->path == NULL)
				{
					parse_uri(r, token_start, (i - token_start));

					// skip over the separating space
					i = g_utf8_next_char(i);
					token_start = i;
				}
				else
				{
					fprintf(stderr, "ERROR - Too many spaces in request line\n");
					req_parser_reset(r);
					return REQ_PARSER_PARSE_INVALID_REQUEST;
				}
			}
			else if (c == '\n')
			{
				if (strncmp("HTTP/1.1", token_start, min(8, i - token_start)) != 0)
				{
					fprintf(stderr, "ERROR - Unsupported HTTP version\n");
					req_parser_reset(r);
					return REQ_PARSER_PARSE_INVALID_REQUEST;
				}
				token_start = NULL;
				mode = MODE_HEADER_LINE;
			}
			break;

		case MODE_HEADER_LINE:
			if (token_start == NULL)
			{
				token_start = i;
			}

			if ((token_start == i) && (c == '\n'))
			{
				result = REQ_PARSER_PARSE_OK;
				mode = MODE_REQUEST_BODY;
			}
			else if ((headerQuark == NULL) && (c == ':'))
			{
				memset(buf, 0, HEADER_BUF_SIZE);
				memcpy(buf, token_start, min((i - token_start), HEADER_BUF_SIZE - 1));
				headerQuark = g_intern_string(buf);
				token_start = NULL;

				// skip over the separating space
				i = g_utf8_next_char(i);
			}
			else if (c == '\n')
			{
				if (!r->headers)
				{
					r->headers = g_tree_new_full(quarkcmp, NULL, NULL, gstring_destroy_notify);
				}

				// Subtract one since we don't want the "\r" in the header
				g_tree_insert(r->headers, (gpointer)headerQuark, g_string_new_len(token_start, (i - token_start) - 1));
				token_start = NULL;
				headerQuark = NULL;
			}
			break;

		case MODE_REQUEST_BODY:
			if (r->body == NULL)
			{
				token_start = i;

				if (!r->headers)
				{
					r->headers = g_tree_new_full(quarkcmp, NULL, NULL, gstring_destroy_notify);
				}

				GString *length_header = g_tree_lookup(r->headers, g_intern_static_string("Content-Length"));
				if (length_header)
				{
					int length = atoi(length_header->str);
					size_t bytes_remaining = len - (data - i);

					if (bytes_remaining < (size_t)length)
					{
						fprintf(stderr, "ERROR - Body incomplete.\n");
						req_parser_reset(r);
						return REQ_PARSER_PARSE_INVALID_REQUEST;
					}

					r->body = g_string_new_len(i, length);
					i = i + length;
				}
				else
				{
					size_t length = len - (data - i);
					r->body = g_string_new_len(i, length);
					i = i + length;
				}
				result = REQ_PARSER_PARSE_OK;
			}
			else if (c == '\n')
			{
				result = REQ_PARSER_PARSE_OK;
			}
			break;
		}
	}

	r->status = result;
	return result;
}
コード例 #26
0
ファイル: text.c プロジェクト: jbohren-forks/dia
static int
text_key_event(Focus *focus, 
	       guint keystate, guint keyval, 
	       const gchar *str, int strlen,
               ObjectChange **change)
{
  Text *text;
  int return_val = FALSE;
  int row, i;
  const char *utf;
  gunichar c;

  *change = NULL;
  
  text = focus->text;

  switch(keyval) {
      case GDK_Up:
      case GDK_KP_Up:
        text->cursor_row--;
        if (text->cursor_row<0)
          text->cursor_row = 0;

        if (text->cursor_pos > text_get_line_strlen(text, text->cursor_row))
          text->cursor_pos = text_get_line_strlen(text, text->cursor_row);

        break;
      case GDK_Down:
      case GDK_KP_Down:
        text->cursor_row++;
        if (text->cursor_row >= text->numlines)
          text->cursor_row = text->numlines - 1;

        if (text->cursor_pos > text_get_line_strlen(text, text->cursor_row))
          text->cursor_pos = text_get_line_strlen(text, text->cursor_row);
    
        break;
      case GDK_Left:
      case GDK_KP_Left:
        if (keystate & GDK_CONTROL_MASK)
	  text_move_cursor(text, WORD_START);
	else
          text->cursor_pos--;
        if (text->cursor_pos<0)
          text->cursor_pos = 0;
        break;
      case GDK_Right:
      case GDK_KP_Right:
        if (keystate & GDK_CONTROL_MASK)
	  text_move_cursor(text, WORD_END);
	else
          text->cursor_pos++;
        if (text->cursor_pos > text_get_line_strlen(text, text->cursor_row))
          text->cursor_pos = text_get_line_strlen(text, text->cursor_row);
        break;
      case GDK_Home:
      case GDK_KP_Home:
        text->cursor_pos = 0;
        break;
      case GDK_End:
      case GDK_KP_End:
        text->cursor_pos = text_get_line_strlen(text, text->cursor_row);
        break;
      case GDK_Delete:
      case GDK_KP_Delete:
        return_val = text_delete_key_handler(focus, change);
        break;
      case GDK_BackSpace:
        return_val = TRUE;
        row = text->cursor_row;
        if (text->cursor_pos <= 0) {
          if (row > 0) {
            *change = text_create_change(text, TYPE_JOIN_ROW, 'Q',
                                         text_get_line_strlen(text, row-1), row-1,
					 focus->obj);
          } else {
            return_val = FALSE;
            break;
          }
        } else {
          utf = text_get_line(text, row);
          for (i = 0; i < (text->cursor_pos - 1); i++)
            utf = g_utf8_next_char (utf);
          c = g_utf8_get_char (utf);
          *change = text_create_change (text, TYPE_DELETE_BACKWARD, c,
                                        text->cursor_pos - 1,
                                        text->cursor_row,
					focus->obj);
        }
        text_delete_backward(text);
        break;
      case GDK_Return:
      case GDK_KP_Enter:
        return_val = TRUE;
        *change = text_create_change(text, TYPE_SPLIT_ROW, 'Q',
                                     text->cursor_pos, text->cursor_row,
				     focus->obj);
        text_split_line(text);
        break;
      case GDK_Shift_L:
      case GDK_Shift_R:
      case GDK_Control_L:
      case GDK_Control_R:
      case GDK_Alt_L:
      case GDK_Alt_R:
      case GDK_Meta_L:
      case GDK_Meta_R:
        return_val = FALSE; /* no text change for modifiers */
        break;
      default:
        if (str || (strlen>0)) {
          if (str && *str == '\r')
            break; /* avoid putting junk into our string */
          return_val = TRUE;
	  *change = change_list_create();
          for (utf = str; utf && *utf && strlen > 0 ;
	       utf = g_utf8_next_char (utf), strlen--) {
	    ObjectChange *step;
            c = g_utf8_get_char (utf);
            
            step = text_create_change (text, TYPE_INSERT_CHAR, c,
                                       text->cursor_pos, text->cursor_row,
				       focus->obj);
	    change_list_add (*change, step);
            text_insert_char (text, c);
          }
        }
        break;
  }  
  
  return return_val;
}
コード例 #27
0
ファイル: dicutil.c プロジェクト: 2ion/gjiten
gint search4string(gint srchtype, GjitenDicfile *dicfile, gchar *srchstrg, guint32 *res_index, gint *hit_pos, gint *res_len, gchar *res_str) { 
  gint search_result;
  gchar *linestart, *lineend; 
  gint copySize = 1023;
  static gchar *linsrchptr;

	if (dicfile->status == DICFILE_NOT_INITIALIZED) {
		if (dicfile_init(dicfile) == FALSE) return SRCH_FAIL; 
	}
	if (dicfile->status != DICFILE_OK) return SRCH_FAIL;

  if ((dicfile != conf.mmaped_dicfile) && (conf.mmaped_dicfile != NULL)) {
    //free mem of previously used dicfile	
		munmap(conf.mmaped_dicfile->mem, conf.mmaped_dicfile->size);
		conf.mmaped_dicfile->mem = NULL;
		conf.mmaped_dicfile = NULL;
	}

	if (conf.mmaped_dicfile == NULL) {
    //mmap dicfile into memory	
		conf.mmaped_dicfile = dicfile;
    dicfile->mem = (gchar *) mmap(NULL, dicfile->size, PROT_READ, MAP_SHARED, dicfile->file, 0);
    if (dicfile->mem == NULL) gjiten_abort_with_msg("mmap() failed\n");
		conf.mmaped_dicfile = dicfile;
  }

  if (srchtype == SRCH_START) {
    linsrchptr = dicfile->mem;
  }
 bad_hit:
  search_result = SRCH_FAIL; // assume search fails 
  linsrchptr = strstr(linsrchptr, srchstrg);
  if (linsrchptr != NULL) {  // if we have a match
    linestart = linsrchptr;
    while ((*linestart != '\n') && (linestart != dicfile->mem)) linestart--; // find beginning of line
    if (linestart == dicfile->mem) {   
      if ((isKanjiChar(g_utf8_get_char(linestart)) == FALSE) && (isKanaChar(g_utf8_get_char(linestart)) == FALSE)) {
				linsrchptr++;
				goto bad_hit;
      }
    }

    linestart++;
    lineend = linestart;
    *hit_pos = linsrchptr - linestart;
    while (*lineend != '\n') { // find end of line
      lineend++;
      if (lineend >= dicfile->mem + dicfile->size) { 
				printf("weird.\n");
				break;
      }
    }
    linsrchptr++;	
    if ((lineend - linestart + 1) < 1023) copySize = lineend - linestart + 1;
    else copySize = 1023;
    strncpy(res_str, linestart, copySize);
    res_str[copySize] = 0;
    *res_index  = (guint32)linestart;
    search_result = SRCH_OK; // search succeeded 
  }
  return search_result;
}
コード例 #28
0
ファイル: indic-lang.c プロジェクト: soubok/libset
static void
indic_engine_break (PangoEngineLang *engine,
		    const char      *text,
		    int              length,
		    PangoAnalysis   *analysis,
		    PangoLogAttr    *attrs,
		    int              attrs_len)
{
  const gchar *p, *next = NULL, *next_next;
  gunichar prev_wc, this_wc, next_wc, next_next_wc;
  gboolean is_conjunct = FALSE;
  int i;

  for (p = text, prev_wc = 0, i = 0;
       p != NULL && p < (text + length);
       p = next, prev_wc = this_wc, i++)
    {
      this_wc = g_utf8_get_char (p);
      next = g_utf8_next_char (p);
      if (next != NULL && next < (text + length))
	{
	  next_wc = g_utf8_get_char (next);
	  next_next = g_utf8_next_char (next);
	}
      else
	{
	  next_wc = 0;
	  next_next = NULL;
	}
      if (next_next != NULL && next_next < (text + length))
	next_next_wc = g_utf8_get_char (next_next);
      else
	next_next_wc = 0;

      switch (analysis->script)
      {
        case PANGO_SCRIPT_SINHALA:
	  /*
	   * TODO: The cursor position should be based on the state table.
	   *       This is the wrong place to be doing this.
	   */

	  /*
	   * The cursor should treat as a single glyph:
	   * SINHALA CONS + 0x0DCA + 0x200D + SINHALA CONS
	   * SINHALA CONS + 0x200D + 0x0DCA + SINHALA CONS
	   */
	  if ((this_wc == 0x0DCA && next_wc == 0x200D)
	      || (this_wc == 0x200D && next_wc == 0x0DCA))
	    {
	      not_cursor_position(&attrs[i]);
	      not_cursor_position(&attrs[i + 1]);
	      is_conjunct = TRUE;
	    }
	  else if (is_conjunct
		   && (prev_wc == 0x200D || prev_wc == 0x0DCA)
		   && this_wc >= 0x0D9A
		   && this_wc <= 0x0DC6)
	    {
	      not_cursor_position(&attrs[i]);
	      is_conjunct = FALSE;
	    }
	  /*
	   * Consonant clusters do NOT result in implicit conjuncts
	   * in SINHALA orthography.
	   */
	  else if (!is_conjunct && prev_wc == 0x0DCA && this_wc != 0x200D)
	    {
	      attrs[i].is_cursor_position = TRUE;
	    }

	  break;

	default:

	  if (prev_wc != 0 && (this_wc == 0x200D || this_wc == 0x200C))
	    {
	      not_cursor_position(&attrs[i]);
	      if (next_wc != 0)
		{
		  not_cursor_position(&attrs[i+1]);
		  if ((next_next_wc != 0) &&
		       (next_wc == 0x09CD ||	/* Bengali */
			next_wc == 0x0ACD ||	/* Gujarati */
			next_wc == 0x094D ||	/* Hindi */
			next_wc == 0x0CCD ||	/* Kannada */
			next_wc == 0x0D4D ||	/* Malayalam */
			next_wc == 0x0B4D ||	/* Oriya */
			next_wc == 0x0A4D ||	/* Punjabi */
			next_wc == 0x0BCD ||	/* Tamil */
			next_wc == 0x0C4D))	/* Telugu */
		    {
		      not_cursor_position(&attrs[i+2]);
		    }
		}
	    }

	  break;
      }
    }
}
コード例 #29
0
ファイル: hangul-fc.c プロジェクト: soubok/libset
static void
render_syllable (PangoFont *font, const char *str, int length,
		 PangoGlyphString *glyphs, int *n_glyphs, int cluster_offset)
{
  int n_prev_glyphs = *n_glyphs;
  int index;
  gunichar wc = 0, tone = 0, text[4];
  int i, j, composed = 0;
  const char *p;

  /* Normalize it only when the entire sequence is equivalent to a
   * precomposed syllable. It's usually better than prefix
   * normalization both for poor-featured fonts and for smart fonts.
   * I have seen no smart font which can render S+T as a syllable
   * form.
   */

  if (length == 3 || length == 4)
    {
      p = str;
      text[0] = g_utf8_get_char(p);
      p = g_utf8_next_char(p);
      text[1] = g_utf8_get_char(p);
      p = g_utf8_next_char(p);
      text[2] = g_utf8_get_char(p);

      if (length == 4 && !IS_M(g_utf8_get_char(g_utf8_next_char(p))))
	goto lvt_out;		/* draw the tone mark later */

      if (IS_L_S(text[0]) && IS_V_S(text[1]) &&  IS_T_S(text[2]))
	{
	  composed = 3;
	  wc = S_FROM_LVT(text[0], text[1], text[2]);
	  str = g_utf8_next_char(p);
	  goto normalize_out;
	}
    }
 lvt_out:

  if (length == 2 || length == 3)
    {
      p = str;
      text[0] = g_utf8_get_char(p);
      p = g_utf8_next_char(p);
      text[1] = g_utf8_get_char(p);

      if (length == 3 && !IS_M(g_utf8_get_char(g_utf8_next_char(p))))
	goto lv_out;		/* draw the tone mark later */
      if (IS_L_S(text[0]) && IS_V_S(text[1]))
	{
	  composed = 2;
	  wc = S_FROM_LV(text[0], text[1]);
	  str = g_utf8_next_char(p);
	}
      else if (IS_S(text[0] && !S_HAS_T(text[0]) && IS_T_S(text[1])))
	{
	  composed = 2;
	  wc = text[0] + (text[1] - TBASE);
	  str = g_utf8_next_char(p);
	  goto normalize_out;
	}
    }
 lv_out:
 normalize_out:

  if (composed)
    {
      index = find_char (font, wc);
      pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
      if (!index)
	set_glyph (font, glyphs, *n_glyphs, cluster_offset,
		   PANGO_GET_UNKNOWN_GLYPH (wc));
      else
	set_glyph (font, glyphs, *n_glyphs, cluster_offset, index);
      (*n_glyphs)++;
      length -= composed;
    }

  /* Render the remaining text as uncomposed forms as a fallback.  */
  for (i = 0; i < length; i++, str = g_utf8_next_char(str))
    {
      int jindex;
      int oldlen;

      wc = g_utf8_get_char(str);

      if (wc == LFILL || wc == VFILL)
	continue;

      if (IS_M(wc))
	{
	  tone = wc;
	  break;
	}

      if (IS_S(wc))
	{
	  oldlen = *n_glyphs;

	  text[0] = L_FROM_S(wc);
	  text[1] = V_FROM_S(wc);
	  if (S_HAS_T(wc))
	    {
	      text[2] = T_FROM_S(wc);
	      composed = 3;
	    }
	  else
	      composed = 2;

	  for (j = 0; j < composed; j++)
	    {
	      index = find_char (font, text[j]);
	      if (index)
		{
		  pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
		  set_glyph (font, glyphs, *n_glyphs, cluster_offset, index);
		  (*n_glyphs)++;
		}
	      else
		goto decompose_cancel;
	    }

	  continue;

	decompose_cancel:
	  /* The font doesn't have jamos.  Cancel it. */
	  *n_glyphs = oldlen;
	  pango_glyph_string_set_size (glyphs, *n_glyphs);
	}

      index = find_char (font, wc);
      if (index)
	{
	  pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
	  set_glyph (font, glyphs, *n_glyphs, cluster_offset, index);
	  (*n_glyphs)++;
	  continue;
	}
      else if (IS_S(wc))
	{
	  pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
	  set_glyph (font, glyphs, *n_glyphs, cluster_offset,
		     PANGO_GET_UNKNOWN_GLYPH (wc));
	  (*n_glyphs)++;
	  continue;
	}

      /* This font has no glyphs on the Hangul Jamo area!  Find a
	 fallback from the Hangul Compatibility Jamo area.  */
      jindex = wc - LBASE;
      oldlen = *n_glyphs;
      for (j = 0; j < 3 && (__jamo_to_ksc5601[jindex][j] != 0); j++)
	{
	  wc = __jamo_to_ksc5601[jindex][j] - KSC_JAMOBASE + UNI_JAMOBASE;
	  index = (wc >= 0x3131) ? find_char (font, wc) : 0;
	  pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
	  if (!index)
	    {
	      *n_glyphs = oldlen;
	      pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
	      set_glyph (font, glyphs, *n_glyphs, cluster_offset,
			 PANGO_GET_UNKNOWN_GLYPH (text[i]));
	      (*n_glyphs)++;
	      break;
	    }
	  else
	    set_glyph (font, glyphs, *n_glyphs, cluster_offset, index);
	  (*n_glyphs)++;
	}
    }
  if (n_prev_glyphs == *n_glyphs)
    {
      index = find_char (font, 0x3164);	/* U+3164 HANGUL FILLER */
      pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
      if (!index)
	set_glyph (font, glyphs, *n_glyphs, cluster_offset,
		   PANGO_GET_UNKNOWN_GLYPH (index));
      else
	set_glyph (font, glyphs, *n_glyphs, cluster_offset, index);
      glyphs->log_clusters[*n_glyphs] = cluster_offset;
      (*n_glyphs)++;
    }
  if (tone)
    render_tone(font, tone, glyphs, n_glyphs, cluster_offset);
}
コード例 #30
0
ファイル: gsb_real.c プロジェクト: philippedelorme/grisbi
/**
 * get a gsb_real number from a string
 * the string can be formatted :
 * - spaces and the given utf8-encoded thousands separators are ignored
 * - handle ",", "." and the given utf8-encoded decimal separator
 * - another character makes a error_real return
 *
 * \param string
 * \param mon_thousands_sep, can be NULL or empty, but only one utf8 sequence
 * \param mon_decimal_point, can be NULL or empty, but only one utf8 sequence
 *
 * \return the number in the string transformed to gsb_real
 */
gsb_real gsb_real_raw_get_from_string ( const gchar *string,
                                        const gchar *mon_thousands_sep,
                                        const gchar *mon_decimal_point )
{
    static gchar *space_chars;
    static gchar *decimal_chars;
    static const gchar *positive_chars = "+";
    static const gchar *negative_chars = "-";
    static const gchar *decimal_char_dot = ".";
    static const gchar *decimal_char_comma = ",";
    static const gchar *empty_char = "" ;
    const gchar *default_decimal_char_dot = decimal_char_dot;
    const gchar *default_decimal_char_comma = decimal_char_comma;
    unsigned mts_len;
    unsigned mdp_len;
    unsigned nb_digits = 0;
    gint64 mantissa = 0;
    gint8 sign = 0;
    gint8 dot_position = -1;
    const gchar *p = string;
    gboolean success = FALSE;

    if ( !string)
        return error_real;

    mts_len = mon_thousands_sep ? strlen ( mon_thousands_sep ) : 0;
    mdp_len = mon_decimal_point ? strlen ( mon_decimal_point ) : 0;

    if ( mon_thousands_sep )
    {
        if ( g_strstr_len ( mon_thousands_sep, -1, decimal_char_dot ) )
            default_decimal_char_dot = empty_char;
        if ( g_strstr_len ( mon_thousands_sep, -1, decimal_char_comma ) )
            default_decimal_char_comma = empty_char ;
    }

    decimal_chars = g_strconcat(default_decimal_char_dot,
                                default_decimal_char_comma,
                                mon_decimal_point,
                                NULL);
    space_chars = g_strconcat(" ", mon_thousands_sep, NULL);

    for ( ; ; )
    {
        if ( g_ascii_isdigit ( *p ) )
        {
            mantissa *= 10;
            mantissa += ( *p - '0' );
            if ( mantissa > G_MAXINT64 )
            {
                break;
            }
            if ( sign == 0 ) sign = 1; /* no sign found yet ==> positive */
            ++nb_digits;
            ++p;
        }
        else if ( *p == 0 ) /* terminal zero */
        {
            success = TRUE;
            break;
        }
        else if ( decimal_chars && strchr ( decimal_chars, *p ) )
        {
            if ( dot_position >= 0 ) /* already found a decimal separator */
            {
                break;
            }
            dot_position = nb_digits;
            p = g_utf8_find_next_char ( p, NULL );
        }
        else if ( g_utf8_strchr ( space_chars, -1,  g_utf8_get_char( p ) ) )
        {
            /* just skip spaces and thousands separators */
            p = g_utf8_find_next_char ( p, NULL );
        }
        else if ( strchr ( negative_chars, *p ) )
        {
            if ( sign != 0 ) /* sign already set */
            {
                break;
            }
            sign = -1;
            ++p;
        }
        else if ( strchr ( positive_chars, *p ) )
        {
            if ( sign != 0 ) /* sign already set */
            {
                break;
            }
            sign = 1;
            ++p;
        }
        else /* unknown char ==> error */
        {
            break;
        }
    }
    /* Free memory */
    g_free ( decimal_chars );
    g_free ( space_chars );
    if (success == TRUE)
    {
        gsb_real result;
        result.mantissa = sign * mantissa;
        result.exponent = ( dot_position >= 0 )
                          ? nb_digits - dot_position
                          : 0;
        return result;
    }
    else
    {
        return error_real;
    }
}