static void e_name_western_cleanup_string (gchar **str) { gchar *newstr; gchar *p; if (*str == NULL) return; /* skip any spaces and commas at the start of the string */ p = *str; while (g_unichar_isspace (g_utf8_get_char (p)) || *p == ',') p = g_utf8_next_char (p); /* make the copy we're going to return */ newstr = g_strdup (p); if ( strlen (newstr) > 0) { /* now search from the back, skipping over any spaces and commas */ p = newstr + strlen (newstr); p = g_utf8_prev_char (p); while (g_unichar_isspace (g_utf8_get_char (p)) || *p == ',') p = g_utf8_prev_char (p); /* advance p to after the character that caused us to exit the * previous loop, and end the string. */ if ((!g_unichar_isspace (g_utf8_get_char (p))) && *p != ',') p = g_utf8_next_char (p); *p = '\0'; } g_free (*str); *str = newstr; }
// move word left static void textbox_cursor_dec_word ( textbox *tb ) { // Find word boundaries, with pango_Break? gchar *n; gchar *c = &( tb->text[tb->cursor] ); while ( ( c = g_utf8_prev_char ( c ) ) && c != tb->text ) { gunichar uc = g_utf8_get_char ( c ); GUnicodeBreakType bt = g_unichar_break_type ( uc ); if ( ( bt == G_UNICODE_BREAK_ALPHABETIC || bt == G_UNICODE_BREAK_HEBREW_LETTER || bt == G_UNICODE_BREAK_NUMERIC || bt == G_UNICODE_BREAK_QUOTATION ) ) { break; } } if ( c != tb->text ) { while ( ( n = g_utf8_prev_char ( c ) ) ) { gunichar uc = g_utf8_get_char ( n ); GUnicodeBreakType bt = g_unichar_break_type ( uc ); if ( !( bt == G_UNICODE_BREAK_ALPHABETIC || bt == G_UNICODE_BREAK_HEBREW_LETTER || bt == G_UNICODE_BREAK_NUMERIC || bt == G_UNICODE_BREAK_QUOTATION ) ) { break; } c = n; if ( n == tb->text ) { break; } } } int index = c - tb->text; textbox_cursor ( tb, index ); }
static gchar * e_name_western_get_preceding_word (gchar *str, gint idx) { gint word_len; gchar *word; gchar *p; p = str + idx; while (g_unichar_isspace (g_utf8_get_char (p)) && p > str) p = g_utf8_prev_char (p); while (!g_unichar_isspace (g_utf8_get_char (p)) && p > str) p = g_utf8_prev_char (p); if (g_unichar_isspace (g_utf8_get_char (p))) p = g_utf8_next_char (p); word_len = (str + idx) - p; word = g_malloc0 (word_len + 1); if (word_len > 0) strncpy (word, p, word_len); return word; }
bool LaunchPoint::matchesTitle(const gchar* str) const { if (!str || !m_title.lowercase) return false; if (g_str_has_prefix(m_title.lowercase, str)) return true; static const gchar* delimiters = " ,._-:;()\\[]{}\"/"; static size_t len = strlen(delimiters); bool matches = false; const gchar* start = m_title.lowercase; while (start != NULL) { start = strstr(start, str); // have we hit the end? if (start == NULL || start == m_title.lowercase) break; // is the previous character in our delimiter set? const gchar c[] = {*g_utf8_prev_char(start), '\0'}; if (strcspn(delimiters, c) < len) { matches = true; break; } start = g_utf8_find_next_char(start, NULL); } return matches; }
/** * seahorse_util_string_trim_whitespace: * @text: The text to trim (UTF8) * * Whitespaces will be removed from the start and the end of the text. */ void seahorse_util_string_trim_whitespace (gchar *text) { gchar *b, *e, *n; g_assert (text); g_assert (g_utf8_validate (text, -1, NULL)); /* Trim the front */ b = text; while (*b && g_unichar_isspace (g_utf8_get_char (b))) b = g_utf8_next_char (b); /* Trim the end */ n = e = b + strlen (b); while (n >= b) { if (*n && !g_unichar_isspace (g_utf8_get_char (n))) break; e = n; n = g_utf8_prev_char (e); } g_assert (b >= text); g_assert (e >= b); *e = 0; g_memmove (text, b, (e + 1) - b); }
static char * strstr_word (const char *haystack, const char *needle) { const char *hay = haystack; while (*hay) { char *n = strstr (hay, needle); gboolean failed = FALSE; if (n == NULL) return NULL; if (n != haystack) { char *prev = g_utf8_prev_char (n); if (g_unichar_isalnum (g_utf8_get_char (prev))) failed = TRUE; } if (! failed) { char *next = n + strlen (needle); if (*next && g_unichar_isalnum (g_utf8_get_char (next))) failed = TRUE; } if (! failed) return n; hay = g_utf8_next_char (hay); } return NULL; }
static gint go_load_pango_byte_to_char (gchar const *str, gint byte) { if (byte >= (gint)strlen (str)) return g_utf8_strlen (str, -1); return g_utf8_pointer_to_offset (str, g_utf8_prev_char (str + byte + 1)); }
static GString * select_word_text(GntTextView *view, gchar *c) { gchar *start = c; gchar *end = c; gchar *t, *endsize; while ((t = g_utf8_prev_char(start))) { if (!g_ascii_isspace(*t)) { if (start == view->string->str) break; start = t; } else break; } while ((t = g_utf8_next_char(end))) { if (!g_ascii_isspace(*t)) end = t; else break; } select_start = start; select_end = end; endsize = g_utf8_next_char(select_end); /* End at the correct byte */ return g_string_new_len(start, endsize - start); }
/** * dt_utf8_strlcpy: * @dest: buffer to fill with characters from @src * @src: UTF-8 encoded string * @n: size of @dest * * Like the BSD-standard strlcpy() function, but * is careful not to truncate in the middle of a character. * The @src string must be valid UTF-8 encoded text. * (Use g_utf8_validate() on all text before trying to use UTF-8 * utility functions with it.) * * Return value: strlen(src) * Implementation by Philip Page, see https://bugzilla.gnome.org/show_bug.cgi?id=520116 **/ size_t dt_utf8_strlcpy(char *dest, const char *src,size_t n) { register const gchar *s = src; while (s - src < n && *s) { s = g_utf8_next_char(s); } if (s - src >= n) { /* We need to truncate; back up one. */ s = g_utf8_prev_char(s); strncpy(dest, src, s - src); dest[s - src] = '\0'; /* Find the full length for return value. */ while (*s) { s = g_utf8_next_char(s); } } else { /* Plenty of room, just copy */ strncpy(dest, src, s - src); dest[s - src] = '\0'; } return s - src; }
static void trim_spaces_inplace (char *field, StfParseOptions_t const *parseoptions) { if (!field) return; if (parseoptions->trim_spaces & TRIM_TYPE_LEFT) { char *s = field; while (g_unichar_isspace (g_utf8_get_char (s))) s = g_utf8_next_char (s); if (s != field) strcpy (field, s); } if (parseoptions->trim_spaces & TRIM_TYPE_RIGHT) { char *s = field + strlen (field); while (field != s) { s = g_utf8_prev_char (s); if (!g_unichar_isspace (g_utf8_get_char (s))) break; *s = 0; } } }
GSList* prof_occurrences(const char *const needle, const char *const haystack, int offset, gboolean whole_word, GSList **result) { if (needle == NULL || haystack == NULL) { return *result; } if (g_str_has_prefix(&haystack[offset], needle)) { if (whole_word) { char *prev = g_utf8_prev_char(&haystack[offset]); char *next = g_utf8_next_char(&haystack[offset] + strlen(needle) - 1); gunichar prevu = g_utf8_get_char(prev); gunichar nextu = g_utf8_get_char(next); if (!g_unichar_isalnum(prevu) && !g_unichar_isalnum(nextu)) { *result = g_slist_append(*result, GINT_TO_POINTER(offset)); } } else { *result = g_slist_append(*result, GINT_TO_POINTER(offset)); } } if (haystack[offset+1] != '\0') { *result = prof_occurrences(needle, haystack, offset+1, whole_word, result); } return *result; }
/* Strip punctuation and white space, more or less Unicode-safe. * The offset of the start of the word is stored in offset if non-NULL. */ static gchar *strip_word(const gchar *word_to_check, gint *result_offset) { gunichar c; gchar *word = g_strdup(word_to_check); gchar *word_start = word; gchar *word_end; gint offset = 0; gint word_len; gint new_word_len; /* strip from the left */ do { c = g_utf8_get_char_validated(word, -1); if (is_word_sep(c)) { /* skip this character */ word = g_utf8_next_char(word); } else break; } while (c != (gunichar) -1 && c != 0 && *word != '\0'); word_len = strlen(word_to_check); offset = word - word_start; new_word_len = word_len - offset; if (new_word_len <= 0) { /* empty or only punctuation in input string */ *result_offset = 0; g_free(word_start); return NULL; } /* move the string in-place and truncate it */ g_memmove(word_start, word, new_word_len); word = word_start; word[new_word_len] = '\0'; if (EMPTY(word)) { g_free(word); return NULL; } /* strip from the right */ word_end = word + strlen(word); do { word_end = g_utf8_prev_char(word_end); c = g_utf8_get_char_validated(word_end, -1); if (is_word_sep(c)) { /* skip this character */ *word_end = '\0'; } else break; } while (c != (gunichar) -1 && word_end >= word); if (result_offset != NULL) *result_offset = offset; return word; }
/* The final " (xx, yy, zz, kk)" part of the string (if present) was * added by us in _to_s(), we must remove it before setting the string * back again. * * It may not be there if the user has changed the string. */ static char * drop_tail( const char *data ) { char *str; char *p; str = g_strdup( data ); p = str + strlen( str ); if( p > str && *g_utf8_prev_char( p ) == ')' && (p = g_utf8_strrchr( str, -1, (gunichar) '(')) && p > str && *(p = g_utf8_prev_char( p )) == ' ' ) *p = '\0'; return( str ); }
// Compares strg1 with strg2. // If strg1 == strg3|strg2 then returns TRUE (End of strg1 matches strg2) int strg_end_compare(gchar *strg1, gchar *strg2) { int i = 0; int matching = TRUE; gchar *strg1_end, *strg2_end; if (strlen(strg1) < strlen(strg2)) return FALSE; strg1_end = strg1 + strlen(strg1); strg2_end = strg2 + strlen(strg2); for (i = 0; i < g_utf8_strlen(strg2, -1); i++) { strg1_end = g_utf8_prev_char(strg1_end); strg2_end = g_utf8_prev_char(strg2_end); if (g_utf8_get_char(strg1_end) != g_utf8_get_char(strg2_end)) matching = FALSE; } return matching; }
static gchar * g_utf8_strrcasestr (const gchar *haystack, const gchar *needle) { gsize needle_len; gsize haystack_len; gchar *ret = NULL; gchar *p; gchar *casefold; gchar *caseless_haystack; gint i; g_return_val_if_fail (haystack != NULL, NULL); g_return_val_if_fail (needle != NULL, NULL); casefold = g_utf8_casefold (haystack, -1); caseless_haystack = g_utf8_normalize (casefold, -1, G_NORMALIZE_ALL); g_free (casefold); needle_len = g_utf8_strlen (needle, -1); haystack_len = g_utf8_strlen (caseless_haystack, -1); if (needle_len == 0) { ret = (gchar *)haystack; goto finally_1; } if (haystack_len < needle_len) { ret = NULL; goto finally_1; } haystack_len = strlen (caseless_haystack); needle_len = strlen (needle); p = (gchar *)caseless_haystack + haystack_len - needle_len; i = haystack_len - needle_len; while (p >= caseless_haystack) { if (strncasecmp (p, needle, needle_len) == 0) { ret = g_utf8_offset_to_pointer (haystack, i); goto finally_1; } p = g_utf8_prev_char (p); i--; } finally_1: g_free (caseless_haystack); return ret; }
static const gchar * utf8_strrcasestr (const gchar *haystack, const gchar *needle) { gsize needle_len; gsize haystack_len; const gchar *ret = NULL; gchar *p; gchar *casefold; gchar *caseless_haystack; gint i; g_return_val_if_fail (haystack != NULL, NULL); g_return_val_if_fail (needle != NULL, NULL); casefold = g_utf8_casefold (haystack, -1); caseless_haystack = g_utf8_normalize (casefold, -1, G_NORMALIZE_NFD); g_free (casefold); needle_len = g_utf8_strlen (needle, -1); haystack_len = g_utf8_strlen (caseless_haystack, -1); if (needle_len == 0) { ret = (gchar *)haystack; goto finally_1; } if (haystack_len < needle_len) { ret = NULL; goto finally_1; } i = haystack_len - needle_len; p = g_utf8_offset_to_pointer (caseless_haystack, i); needle_len = strlen (needle); while (p >= caseless_haystack) { if (exact_prefix_cmp (p, needle, needle_len)) { ret = pointer_from_offset_skipping_decomp (haystack, i); goto finally_1; } p = g_utf8_prev_char (p); i--; } finally_1: g_free (caseless_haystack); return ret; }
static void str_utf8_cprev_char_safe (const char **text) { const char *result = g_utf8_prev_char (*text); const char *t = result; str_utf8_cnext_char_safe (&t); if (t == *text) (*text) = result; else (*text)--; }
static int get_field_value (char *out, int size, const char *key, const char *(*getter)(DB_playItem_t *it, const char *key), int (*equals)(const char *a, const char *b), DB_playItem_t **tracks, int numtracks) { int multiple = 0; *out = 0; if (numtracks == 0) { return 0; } char *p = out; deadbeef->pl_lock (); const char **prev = malloc (sizeof (const char *) * numtracks); memset (prev, 0, sizeof (const char *) * numtracks); for (int i = 0; i < numtracks; i++) { const char *val = getter (tracks[i], key); if (val && val[0] == 0) { val = NULL; } if (i > 0 || (val && strlen (val) >= MAX_GUI_FIELD_LEN)) { int n = 0; for (; n < i; n++) { if (equals (prev[n], val)) { break; } } if (n == i || (val && strlen (val) >= MAX_GUI_FIELD_LEN)) { multiple = 1; if (val) { size_t l = snprintf (out, size, out == p ? "%s" : "; %s", val ? val : ""); l = min (l, size); out += l; size -= l; } } } else if (val) { size_t l = snprintf (out, size, "%s", val ? val : ""); l = min (l, size); out += l; size -= l; } prev[i] = val; if (size <= 1) { break; } } deadbeef->pl_unlock (); if (size <= 1) { gchar *prev = g_utf8_prev_char (out-4); strcpy (prev, "..."); } free (prev); return multiple; }
static guint infinoted_plugin_linekeeper_count_lines(InfTextBuffer* buffer) { /* Count the number of lines at the end of the document. This assumes the * buffer content is in UTF-8, which is currently hardcoded in infinoted. */ InfTextBufferIter* iter; guint n_lines; gboolean has_iter; guint length; gsize bytes; gchar* text; gchar* pos; gchar* new_pos; gunichar c; g_assert(strcmp(inf_text_buffer_get_encoding(buffer), "UTF-8") == 0); n_lines = 0; iter = inf_text_buffer_create_end_iter(buffer); if(iter == NULL) return 0; do { length = inf_text_buffer_iter_get_length(buffer, iter); bytes = inf_text_buffer_iter_get_bytes(buffer, iter); text = inf_text_buffer_iter_get_text(buffer, iter); pos = text + bytes; while(length > 0) { new_pos = g_utf8_prev_char(pos); g_assert(bytes >= (pos - new_pos)); c = g_utf8_get_char(new_pos); if(c == '\n' || g_unichar_type(c) == G_UNICODE_LINE_SEPARATOR) ++n_lines; else break; --length; bytes -= (pos - new_pos); pos = new_pos; } g_free(text); } while(length == 0 && inf_text_buffer_iter_prev(buffer, iter)); inf_text_buffer_destroy_iter(buffer, iter); return n_lines; }
/** * Retrieve a possible address (or a part) from an entry box. To make life * easier, we only look at the last valid address component; address * completion only works at the last string component in the entry box. * * \param entry Address entry field. * \param start_pos Address of start position of address. * \return Possible address. */ static gchar *get_address_from_edit(GtkEntry *entry, gint *start_pos) { const gchar *edit_text, *p; gint cur_pos; gboolean in_quote = FALSE; gboolean in_bracket = FALSE; gchar *str; edit_text = gtk_entry_get_text(entry); if (edit_text == NULL) return NULL; cur_pos = gtk_editable_get_position(GTK_EDITABLE(entry)); /* scan for a separator. doesn't matter if walk points at null byte. */ for (p = g_utf8_offset_to_pointer(edit_text, cur_pos); p > edit_text; p = g_utf8_prev_char(p)) { if (*p == '"') { in_quote = TRUE; } else if (!in_quote) { if (!in_bracket && *p == ',') { break; } else if (*p == '<') in_bracket = TRUE; else if (*p == '>') in_bracket = FALSE; } } /* have something valid */ if (g_utf8_strlen(p, -1) == 0) return NULL; #define IS_VALID_CHAR(x) \ (g_ascii_isalnum(x) || (x) == '"' || (x) == '<' || (((unsigned char)(x)) > 0x7f)) /* now scan back until we hit a valid character */ for (; *p && !IS_VALID_CHAR(*p); p = g_utf8_next_char(p)) ; #undef IS_VALID_CHAR if (g_utf8_strlen(p, -1) == 0) return NULL; if (start_pos) *start_pos = g_utf8_pointer_to_offset(edit_text, p); str = g_strdup(p); return str; }
static gchar * e_name_western_get_suffix_at_str_end (gchar *str) { gchar *suffix; gchar *p; /* * Walk backwards till we reach the beginning of the * (potentially-comma-separated) list of suffixes. */ p = str + strlen (str); while (1) { gchar *nextp; gchar *word; word = e_name_western_get_preceding_word (str, p - str); nextp = p - strlen (word); if (nextp == str) { g_free (word); break; } nextp = g_utf8_prev_char (nextp); e_name_western_cleanup_string (& word); if (e_name_western_word_is_suffix (word)) { p = nextp; g_free (word); } else { g_free (word); break; } } if (p == (str + strlen (str))) return NULL; suffix = g_strdup (p); e_name_western_cleanup_string (& suffix); if (strlen (suffix) == 0) { g_free (suffix); return NULL; } return suffix; }
///! ///! @brief This allows searching for fish, and getting bigfish back if the morphology parser doesn't catch it ///! static void _lw_index_index_subkeys_by_type (LwIndex *index, LwIndexTableType type, const gchar *KEY) { //Sanity checks g_return_val_if_fail (index != NULL, NULL); g_return_val_if_fail (KEY != NULL, NULL); //Declarations gchar *key_copy = NULL; gchar *ptr = NULL; const gchar *subkey = NULL; //Initializations key_copy = g_strdup (KEY); if (key_copy == NULL) goto errored; ptr = key_copy; if (*ptr != '\0') ptr = g_utf8_next_char (ptr); //Search for substrings by removing the front characters while (ptr != NULL && *ptr != '\0') { ptr = g_utf8_next_char (ptr); subkey = ptr; GUnicodeScript script = g_unichar_get_script (g_utf8_get_char (subkey)); gboolean has_relevance = (*subkey != '\0' && (g_utf8_strlen (subkey, 9) > 2 || script == G_UNICODE_SCRIPT_HAN)); if (has_relevance && g_hash_table_contains (index->table[type], subkey)) { _lw_index_concat_masterkey_to_subkey (index, type, KEY, subkey); } } //Search for substring by removing the back characters subkey = key_copy; GUnicodeScript script = g_unichar_get_script (g_utf8_get_char (subkey)); while (ptr > subkey) { ptr = g_utf8_prev_char (ptr); *ptr = '\0'; gboolean has_relevance = (*subkey != '\0' && (g_utf8_strlen (subkey, 9) > 2 || script == G_UNICODE_SCRIPT_HAN)); if (has_relevance && g_hash_table_contains (index->table[type], subkey)) { _lw_index_concat_masterkey_to_subkey (index, type, KEY, subkey); } } errored: if (key_copy != NULL) g_free (key_copy); key_copy = NULL; }
static int grind_get_char_backwards (const char *str, gsize len) { gunichar acc = 0; int i; for (i = 0; i < NUM_ITERATIONS; i++) { const char *p = str + len; do { p = g_utf8_prev_char (p); acc += g_utf8_get_char (p); } while (p != str); } return acc; }
/* TODO: Should be perfectly possible to make this modify the string in-place */ gchar * gdata_parser_utf8_trim_whitespace (const gchar *s) { glong len; const gchar *_s; /* Skip the leading whitespace */ while (*s != '\0' && g_unichar_isspace (g_utf8_get_char (s))) s = g_utf8_next_char (s); /* Find the end of the string and backtrack until we've passed all the whitespace */ len = g_utf8_strlen (s, -1); _s = g_utf8_offset_to_pointer (s, len - 1); while (len > 0 && g_unichar_isspace (g_utf8_get_char (_s))) { _s = g_utf8_prev_char (_s); len--; } _s = g_utf8_next_char (_s); return g_strndup (s, _s - s); }
static gboolean match_is_word (const char *src, const GORegmatch *pm, gboolean bolp) { /* The empty string is not a word. */ if (pm->rm_so == pm->rm_eo) return FALSE; if (pm->rm_so > 0 || !bolp) { /* We get here when something actually preceded the match. */ gunichar c_pre = g_utf8_get_char (g_utf8_prev_char (src + pm->rm_so)); if (g_unichar_isalnum (c_pre)) return FALSE; } { gunichar c_post = g_utf8_get_char (src + pm->rm_eo); if (c_post != 0 && g_unichar_isalnum (c_post)) return FALSE; } return TRUE; }
//Finds out if the result is EXACT_MATCH, START_WITH_MATCH, END_WITH_MATCH, ANY_MATCH int get_jp_match_type(gchar *line, gchar *srchstrg, int offset) { int srchstrglen; srchstrglen = strlen(srchstrg); if (offset == 0) { //can be EXACT or START_WITH if ((*(line + srchstrglen)) == ' ') return EXACT_MATCH; return START_WITH_MATCH; } else { //Check for Furigana if (g_unichar_isalpha(g_utf8_get_char(g_utf8_prev_char(line + offset))) == FALSE) { if (g_unichar_isalpha(g_utf8_get_char(line + offset + srchstrglen)) == FALSE) { return EXACT_MATCH; } else return START_WITH_MATCH; } else { // has an alpha char before if (g_unichar_isalpha(g_utf8_get_char(line + offset + srchstrglen)) == FALSE) return END_WITH_MATCH; } } if ((*(line + offset + srchstrglen)) == ' ') return END_WITH_MATCH; return ANY_MATCH; }
static char * find_word (const char *full_name, const char *word, int word_len, gboolean whole_word, gboolean is_first_word) { char *p = (char *)full_name - 1; while ((p = strchr (p + 1, *word))) { if (strncmp (p, word, word_len) != 0) continue; if (p > (char *)full_name) { char *prev = g_utf8_prev_char (p); /* Make sure p points to the start of a word */ if (g_unichar_isalpha (g_utf8_get_char (prev))) continue; /* If we're matching the first word of the key, it has to * match the first word of the location, city, state, or * country. Eg, it either matches the start of the string * (which we already know it doesn't at this point) or * it is preceded by the string ", " (which isn't actually * a perfect test. FIXME) */ if (is_first_word) { if (prev == (char *)full_name || strncmp (prev - 1, ", ", 2) != 0) continue; } } if (whole_word && g_unichar_isalpha (g_utf8_get_char (p + word_len))) continue; return p; } return NULL; }
int dt_control_key_pressed_override(guint key, guint state) { dt_control_accels_t *accels = &darktable.control->accels; // TODO: if darkroom mode // did a : vim-style command start? static GList *autocomplete = NULL; static char vimkey_input[256]; if(darktable.control->vimkey_cnt) { guchar unichar = gdk_keyval_to_unicode(key); if(key == GDK_KEY_Return) { if(!strcmp(darktable.control->vimkey, ":q")) { dt_control_quit(); } else { dt_bauhaus_vimkey_exec(darktable.control->vimkey); } darktable.control->vimkey[0] = 0; darktable.control->vimkey_cnt = 0; dt_control_log_ack_all(); g_list_free(autocomplete); autocomplete = NULL; } else if(key == GDK_KEY_Escape) { darktable.control->vimkey[0] = 0; darktable.control->vimkey_cnt = 0; dt_control_log_ack_all(); g_list_free(autocomplete); autocomplete = NULL; } else if(key == GDK_KEY_BackSpace) { darktable.control->vimkey_cnt -= (darktable.control->vimkey + darktable.control->vimkey_cnt) - g_utf8_prev_char(darktable.control->vimkey + darktable.control->vimkey_cnt); darktable.control->vimkey[darktable.control->vimkey_cnt] = 0; if(darktable.control->vimkey_cnt == 0) dt_control_log_ack_all(); else dt_control_log("%s", darktable.control->vimkey); g_list_free(autocomplete); autocomplete = NULL; } else if(key == GDK_KEY_Tab) { // TODO: also support :preset and :get? // auto complete: if(darktable.control->vimkey_cnt < 5) { snprintf(darktable.control->vimkey, sizeof(darktable.control->vimkey), ":set "); darktable.control->vimkey_cnt = 5; } else if(!autocomplete) { // TODO: handle '.'-separated things separately // this is a static list, and tab cycles through the list g_strlcpy(vimkey_input, darktable.control->vimkey + 5, sizeof(vimkey_input)); autocomplete = dt_bauhaus_vimkey_complete(darktable.control->vimkey + 5); autocomplete = g_list_append(autocomplete, vimkey_input); // remember input to cycle back } if(autocomplete) { // pop first. // the paths themselves are owned by bauhaus, // no free required. snprintf(darktable.control->vimkey, sizeof(darktable.control->vimkey), ":set %s", (char *)autocomplete->data); autocomplete = g_list_remove(autocomplete, autocomplete->data); darktable.control->vimkey_cnt = strlen(darktable.control->vimkey); } dt_control_log("%s", darktable.control->vimkey); } else if(g_unichar_isprint(unichar)) // printable unicode character { gchar utf8[6]; gint char_width = g_unichar_to_utf8(unichar, utf8); if(darktable.control->vimkey_cnt + 1 + char_width < 256) { g_utf8_strncpy(darktable.control->vimkey + darktable.control->vimkey_cnt, utf8, 1); darktable.control->vimkey_cnt += char_width; darktable.control->vimkey[darktable.control->vimkey_cnt] = 0; dt_control_log("%s", darktable.control->vimkey); g_list_free(autocomplete); autocomplete = NULL; } } else if(key == GDK_KEY_Up) { // TODO: step history up and copy to vimkey } else if(key == GDK_KEY_Down) { // TODO: step history down and copy to vimkey } return 1; } else if(key == ':' && darktable.control->key_accelerators_on) { darktable.control->vimkey[0] = ':'; darktable.control->vimkey[1] = 0; darktable.control->vimkey_cnt = 1; dt_control_log("%s", darktable.control->vimkey); return 1; } /* check if key accelerators are enabled*/ if(darktable.control->key_accelerators_on != 1) return 0; if(key == accels->global_sideborders.accel_key && state == accels->global_sideborders.accel_mods) { /* toggle panel viewstate */ dt_ui_toggle_panels_visibility(darktable.gui->ui); /* trigger invalidation of centerview to reprocess pipe */ dt_dev_invalidate(darktable.develop); gtk_widget_queue_draw(dt_ui_center(darktable.gui->ui)); return 1; } else if(key == accels->global_header.accel_key && state == accels->global_header.accel_mods) { char key[512]; const dt_view_t *cv = dt_view_manager_get_current_view(darktable.view_manager); /* do nothing if in collapse panel state TODO: reconsider adding this check to ui api */ g_snprintf(key, sizeof(key), "%s/ui/panel_collaps_state", cv->module_name); if(dt_conf_get_int(key)) return 0; /* toggle the header visibility state */ g_snprintf(key, sizeof(key), "%s/ui/show_header", cv->module_name); gboolean header = !dt_conf_get_bool(key); dt_conf_set_bool(key, header); /* show/hide the actual header panel */ dt_ui_panel_show(darktable.gui->ui, DT_UI_PANEL_TOP, header, TRUE); gtk_widget_queue_draw(dt_ui_center(darktable.gui->ui)); return 1; } return 0; }
gboolean gsf_output_csv_write_field (GsfOutputCsv *csv, char const *field, size_t len) { gboolean quote; gboolean ok; char const *end; g_return_val_if_fail (GSF_IS_OUTPUT_CSV (csv), FALSE); g_return_val_if_fail (field != NULL, FALSE); if (len == (size_t)-1) len = strlen (field); end = field + len; if (csv->fields_on_line && csv->separator_len) g_string_append_len (csv->buf, csv->separator, csv->separator_len); csv->fields_on_line = TRUE; switch (csv->quoting_mode) { default: case GSF_OUTPUT_CSV_QUOTING_MODE_NEVER: quote = FALSE; break; case GSF_OUTPUT_CSV_QUOTING_MODE_ALWAYS: quote = TRUE; break; case GSF_OUTPUT_CSV_QUOTING_MODE_AUTO: { char const *p = field; quote = FALSE; while (p < end) { gunichar c = g_utf8_get_char (p); if (g_utf8_strchr (csv->quoting_triggers, -1, c)) { quote = TRUE; break; } p = g_utf8_next_char (p); } if (!quote && *field && (g_unichar_isspace (g_utf8_get_char (field)) || g_unichar_isspace (g_utf8_get_char (g_utf8_prev_char (p)))) && g_object_get_data (G_OBJECT (csv), HACK_QUOTING_ON_WHITESPACE) != NULL) quote = TRUE; break; } } if (quote && csv->quote_len > 0) { g_string_append_len (csv->buf, csv->quote, csv->quote_len); while (field < end) { gunichar c = g_utf8_get_char (field); if (g_utf8_strchr (csv->quote, -1, c)) g_string_append_len (csv->buf, csv->quote, csv->quote_len); g_string_append_unichar (csv->buf, c); field = g_utf8_next_char (field); } g_string_append_len (csv->buf, csv->quote, csv->quote_len); } else g_string_append_len (csv->buf, field, len); ok = gsf_output_write (csv->sink, csv->buf->len, csv->buf->str); g_string_truncate (csv->buf, 0); return ok; }
static void get_tag_location (IdeXmlSax *self, gint *line, gint *line_offset, gint *end_line, gint *end_line_offset, const gchar **content, gsize *size) { xmlParserInput *input; const gchar *base; const gchar *current; const gchar *end_current; const gchar *line_start; const gchar *end_line_start; gint start_line_number; gint end_line_number; gint size_offset = 1; gunichar ch; gboolean end_line_found = FALSE; g_assert (IDE_IS_XML_SAX (self)); g_assert (line != NULL); g_assert (line_offset != NULL); g_assert (end_line != NULL); g_assert (end_line_offset != NULL); g_assert (content != NULL); g_assert (size != NULL); /* TODO: handle other types of line break */ input = self->context->input; base = (const gchar *)input->base; current = (const gchar *)input->cur; *end_line = end_line_number = start_line_number = xmlSAX2GetLineNumber (self->context); /* Adjust the element size, can be a start, a end or an auto-closed one */ ch = g_utf8_get_char (current); if (ch != '>') { /* End element case */ if (current > base && g_utf8_get_char (current - 1) == '>') { --current; size_offset = 0; } /* Auto-closed start element case */ else if (ch == '/' && g_utf8_get_char (current + 1) == '>') { ++current; size_offset = 2; } /* Not properly closed tag */ else { ch = g_utf8_get_char (--current); if (ch == '<') { /* Empty node */ *line = *end_line = end_line_number; *line_offset = *end_line_offset = xmlSAX2GetColumnNumber (self->context) - 1; *size = 1; return; } else { while (current >= base) { if (ch == '\n') --end_line_number; if (!g_unichar_isspace (ch) || current == base) break; current = g_utf8_prev_char (current); ch = g_utf8_get_char (current); } end_current = current; *end_line = start_line_number = end_line_number; size_offset = 0; goto next; } } } end_current = current; if (g_utf8_get_char (current) != '>') { *line = start_line_number; *line_offset = *end_line_offset = xmlSAX2GetColumnNumber (self->context); *content = NULL; *size = 0; return; } next: /* Search back the tag start and adjust the start and end line */ while (current > base) { ch = g_utf8_get_char (current); if (ch == '<') break; if (ch == '\n') { --start_line_number; if (!end_line_found ) { end_line_start = current + 1; end_line_found = TRUE; } } current = g_utf8_prev_char (current); } /* Search back the tag start offset */ line_start = current; while (line_start > base) { ch = g_utf8_get_char (line_start); if (ch == '\n') { ++line_start; if (!end_line_found ) { end_line_start = line_start; end_line_found = TRUE; } break; } line_start = g_utf8_prev_char (line_start); } if (!end_line_found) end_line_start = line_start; *line = start_line_number; *line_offset = (current - line_start) + 1; *end_line_offset = (end_current - end_line_start) + 1; *content = current; *size = (const gchar *)input->cur - current + size_offset; }