/** * 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; }
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; } } }
/* 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; }
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; }
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); }
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); }
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 {
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; }
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; }
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); }
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; }
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 */ }
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); }
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); }
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)); } }
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; }
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); }
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); }
/** * 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; }
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); }
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; }
/** 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. */ }
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; }
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; } } }
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; }
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; }
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; }
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; } } }
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); }
/** * 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; } }