static gboolean backspace(GntBindable *bind, GList *null) { int len; GntEntry *entry = GNT_ENTRY(bind); if (entry->cursor <= entry->start) return TRUE; len = entry->cursor - g_utf8_find_prev_char(entry->start, entry->cursor); update_kill_ring(entry, ENTRY_JAIL, entry->cursor, -len); entry->cursor -= len; memmove(entry->cursor, entry->cursor + len, entry->end - entry->cursor); entry->end -= len; if (entry->scroll > entry->start) entry->scroll = g_utf8_find_prev_char(entry->start, entry->scroll); entry_redraw(GNT_WIDGET(entry)); if (entry->ddown) show_suggest_dropdown(entry); entry_text_changed(entry); return TRUE; }
/* query user for a string and jump to the entry * which begins with this string while the users types */ void screen_jump(struct list_window *lw, list_window_callback_fn_t callback_fn, list_window_paint_callback_t paint_callback, void *callback_data) { char *search_str, *iter, *temp; const int WRLN_MAX_LINE_SIZE = 1024; int key = 65; command_t cmd; if (screen.findbuf) { g_free(screen.findbuf); screen.findbuf = NULL; } screen.findbuf = g_malloc0(WRLN_MAX_LINE_SIZE); /* In screen.findbuf is the whole string which is displayed in the status_window * and search_str is the string the user entered (without the prompt) */ search_str = screen.findbuf + g_snprintf(screen.findbuf, WRLN_MAX_LINE_SIZE, "%s: ", JUMP_PROMPT); iter = search_str; while(1) { key = screen_getch(screen.findbuf); /* if backspace or delete was pressed, process instead of ending loop */ if (key == KEY_BACKSPACE || key == KEY_DC) { int i; if (search_str <= g_utf8_find_prev_char(screen.findbuf, iter)) iter = g_utf8_find_prev_char(screen.findbuf, iter); for (i = 0; *(iter + i) != '\0'; i++) *(iter + i) = '\0'; continue; } /* if a control key was pressed, end loop */ else if (g_ascii_iscntrl(key) || key == KEY_NPAGE || key == KEY_PPAGE) { break; } else { *iter = key; if (iter < screen.findbuf + WRLN_MAX_LINE_SIZE - 3) ++iter; } list_window_jump(lw, callback_fn, callback_data, search_str); /* repaint the list_window */ if (paint_callback != NULL) list_window_paint2(lw, paint_callback, callback_data); else list_window_paint(lw, callback_fn, callback_data); wrefresh(lw->w); } /* ncmpc should get the command */ ungetch(key); if ((cmd=get_keyboard_command()) != CMD_NONE) do_input_event(cmd); temp = g_strdup(search_str); g_free(screen.findbuf); screen.findbuf = temp; }
static gboolean transpose_chars(GntBindable *bind, GList *null) { GntEntry *entry = GNT_ENTRY(bind); char *current, *prev; char hold[8]; /* that's right */ if (entry->cursor <= entry->start) return FALSE; if (!*entry->cursor) entry->cursor = g_utf8_find_prev_char(entry->start, entry->cursor); current = entry->cursor; prev = g_utf8_find_prev_char(entry->start, entry->cursor); move_forward(bind, null); /* Let's do this dance! */ memcpy(hold, prev, current - prev); memmove(prev, current, entry->cursor - current); memcpy(prev + (entry->cursor - current), hold, current - prev); update_kill_ring(entry, ENTRY_JAIL, NULL, 0); entry_redraw(GNT_WIDGET(entry)); entry_text_changed(entry); return TRUE; }
char *TextEdit::prevChar(const char *p) const { if (p >= gapend) { if ((p = g_utf8_find_prev_char(gapend, p))) return const_cast<char*>(p); else p = gapstart; } if ((p = g_utf8_find_prev_char(buffer, p))) return const_cast<char*>(p); else return const_cast<char*>(buffer); }
static const char * begin_word(const char *text, const char *begin) { gunichar ch = 0; while (text > begin && (!*text || g_unichar_isspace(g_utf8_get_char(text)))) text = g_utf8_find_prev_char(begin, text); ch = g_utf8_get_char(text); while ((text = g_utf8_find_prev_char(begin, text)) >= begin) { gunichar cur = g_utf8_get_char(text); if (!SAME(ch, cur)) break; } return (text ? g_utf8_find_next_char(text, NULL) : begin); }
/** * g_completion_complete_utf8: * @cmp: the #GCompletion * @prefix: the prefix string, typically used by the user, which is compared * with each of the items * @new_prefix: if non-%NULL, returns the longest prefix which is common to all * items that matched @prefix, or %NULL if no items matched @prefix. * This string should be freed when no longer needed. * * Attempts to complete the string @prefix using the #GCompletion target items. * In contrast to g_completion_complete(), this function returns the largest common * prefix that is a valid UTF-8 string, omitting a possible common partial * character. * * You should use this function instead of g_completion_complete() if your * items are UTF-8 strings. * * Return value: the list of items whose strings begin with @prefix. This should * not be changed. * * Since: 2.4 * * Deprecated: 2.26: Rarely used API **/ GList* g_completion_complete_utf8 (GCompletion *cmp, const gchar *prefix, gchar **new_prefix) { GList *list; gchar *p, *q; list = g_completion_complete (cmp, prefix, new_prefix); if (new_prefix && *new_prefix) { p = *new_prefix + strlen (*new_prefix); q = g_utf8_find_prev_char (*new_prefix, p); switch (g_utf8_get_char_validated (q, p - q)) { case (gunichar)-2: case (gunichar)-1: *q = 0; break; default: ; } } return list; }
static gboolean del_prev_word(GntBindable *bind, GList *null) { GntWidget *widget = GNT_WIDGET(bind); GntEntry *entry = GNT_ENTRY(bind); char *iter = g_utf8_find_prev_char(entry->start, entry->cursor); int count; if (iter < entry->start) return TRUE; iter = (char*)begin_word(iter, entry->start); count = entry->cursor - iter; update_kill_ring(entry, ENTRY_DEL_BWD_WORD, iter, count); memmove(iter, entry->cursor, entry->end - entry->cursor); entry->end -= count; entry->cursor = iter; if (entry->cursor <= entry->scroll) { entry->scroll = entry->cursor - widget->priv.width + 2; if (entry->scroll < entry->start) entry->scroll = entry->start; } memset(entry->end, '\0', entry->buffer - (entry->end - entry->start)); entry_redraw(widget); entry_text_changed(entry); return TRUE; }
static gchar *line_from_buffer(gchar *buffer, guint offset) { gint i,j; i=j=offset; while (i >=0 && i > (offset-40)) { if (buffer[i] == '\n' || buffer[i] == '\r') { break; } i--; } if (i <= offset-40) { gchar *tmp = g_utf8_find_next_char(buffer+i, NULL); if (tmp) i = tmp-buffer; } else { i++; } while (buffer[j] !='\0' && j < (offset+40)) { if (buffer[j] == '\n' || buffer[j] == '\r') { break; } j++; } if (j >= offset+40) { gchar *tmp = g_utf8_find_prev_char(buffer, buffer+j); if (tmp) j = tmp-buffer; } return g_strndup(buffer+i, j-i); }
/* Try to move the cursor backward n characters. Does not modify command line if unsuccessful. */ gboolean cmd_backward(struct cmdline* cmd, gint n, gboolean do_it) { g_return_val_if_fail(n >= 0, FALSE); if (cmd->is_utf8) { gint i; gint new_pos = cmd->pos; for (i = 0; i < n; i++) { gchar* prev = g_utf8_find_prev_char(cmd->data->str, cmd->data->str + new_pos); if (!prev) return FALSE; new_pos = prev - cmd->data->str; } if (do_it) cmd->pos = new_pos; } else { /* Just need to shift by n. */ if (cmd->pos - n >= 0) { if (do_it) cmd->pos -= n; } else return FALSE; } return TRUE; }
/*! \brief Get name and value from an attribute 'name=value' string. * \par Function Description * This function parses the character string \a string expected to be * an attribute string of the form 'name=value'. * * It returns TRUE if it has been able to parse the string into the * name and value parts of an attribute. Otherwise it returns FALSE, * in that case \a *name_ptr and \a *value_ptr are set to NULL. * * \a name_ptr and/or \a value_ptr can be NULL. * If not NULL, the caller must g_free these returned strings. * * \note * If you get an invalid attribute (improper) with a name and no * value, then it is NOT an attribute. Also, there cannot be any * spaces beside the equals sign * * \param [in] string String to split into name/value pair. * \param [out] name_ptr The return location for the name, or NULL. * \param [out] value_ptr The return location for the value, or NULL. * \return TRUE on success, FALSE otherwise. */ gboolean o_attrib_string_get_name_value (const gchar *string, gchar **name_ptr, gchar **value_ptr) { gchar *ptr, *prev_char, *next_char; if (name_ptr != NULL) *name_ptr = NULL; if (value_ptr != NULL) *value_ptr = NULL; g_return_val_if_fail (string != NULL, FALSE); ptr = g_utf8_strchr (string, -1, g_utf8_get_char ("=")); if (ptr == NULL) { return FALSE; } prev_char = g_utf8_find_prev_char (string, ptr); next_char = g_utf8_find_next_char (ptr, NULL); if (prev_char == NULL || *prev_char == ' ' || next_char == NULL || *next_char == ' ' || *next_char == '\0' ) { return FALSE; } if (name_ptr != NULL) { *name_ptr = g_strndup (string, (ptr - string)); } if (value_ptr != NULL) { *value_ptr = g_strdup (next_char); } return TRUE; }
/************************************************************************** Autocompletes the input line with a player or user name. Returns FALSE if there is no string to complete. **************************************************************************/ static bool chatline_autocomplete(GtkEditable *editable) { #define MAX_MATCHES 10 const char *name[MAX_MATCHES]; char buf[MAX_LEN_NAME * MAX_MATCHES]; gint pos; gchar *chars, *p, *prev; int num, i; size_t prefix_len; /* Part 1: get the string to complete. */ pos = gtk_editable_get_position(editable); chars = gtk_editable_get_chars(editable, 0, pos); p = chars + strlen(chars); while ((prev = g_utf8_find_prev_char(chars, p))) { if (!g_unichar_isalnum(g_utf8_get_char(prev))) { break; } p = prev; } /* p points to the start of the last word, or the start of the string. */ prefix_len = g_utf8_strlen(p, -1); if (0 == prefix_len) { /* Empty: nothing to complete, propagate the event. */ g_free(chars); return FALSE; } /* Part 2: compare with player and user names. */ num = check_player_or_user_name(p, name, MAX_MATCHES); if (1 == num) { gtk_editable_delete_text(editable, pos - prefix_len, pos); pos -= prefix_len; gtk_editable_insert_text(editable, name[0], strlen(name[0]), &pos); gtk_editable_set_position(editable, pos); g_free(chars); return TRUE; } else if (num > 1) { if (get_common_prefix(name, num, buf, sizeof(buf)) > prefix_len) { gtk_editable_delete_text(editable, pos - prefix_len, pos); pos -= prefix_len; gtk_editable_insert_text(editable, buf, strlen(buf), &pos); gtk_editable_set_position(editable, pos); } sz_strlcpy(buf, name[0]); for (i = 1; i < num; i++) { cat_snprintf(buf, sizeof(buf), ", %s", name[i]); } /* TRANS: comma-separated list of player/user names for completion */ output_window_printf(ftc_client, _("Suggestions: %s."), buf); } g_free(chars); return TRUE; }
static char * truncate_name (const char *name) { const char *end; end = g_utf8_find_prev_char (name, name + 64); g_assert (end != NULL); return g_strndup (name, end - name); }
static void text_move_cursor(Text *text, CursorMovement mv) { gchar *str = text_line_get_string(text->lines[text->cursor_row]); gchar *p = str; int curmax = text_get_line_strlen(text, text->cursor_row); if (text->cursor_pos > 0 && text->cursor_pos <= curmax) { int i; for (i = 0; i < text->cursor_pos; ++i) p = g_utf8_next_char (p); } if (WORD_START == mv && text->cursor_pos < 1) { if (text->cursor_row) { text->cursor_row--; text->cursor_pos = text_get_line_strlen(text, text->cursor_row); } return; } else if (WORD_END == mv && text->cursor_pos == curmax) { if (text->cursor_row < text->numlines - 1) { text->cursor_row++; text->cursor_pos = 0; } return; } while (!g_unichar_isalnum (g_utf8_get_char (p))) { p = (WORD_START == mv ? g_utf8_find_prev_char (str, p) : g_utf8_next_char (p)); if (p) text->cursor_pos += (WORD_START == mv ? -1 : 1); if (!p || !*p) return; if (!text->cursor_pos || text->cursor_pos == curmax) return; } while (g_unichar_isalnum (g_utf8_get_char (p))) { p = (WORD_START == mv ? g_utf8_find_prev_char (str, p) : g_utf8_next_char (p)); if (p) text->cursor_pos += (WORD_START == mv ? -1 : 1); if (!p || !*p) return; if (!text->cursor_pos || text->cursor_pos == curmax) return; } }
const char* mime_cache_lookup_suffix( MimeCache* cache, const char* filename, const char** suffix_pos ) { const char* root = cache->suffix_roots; int i, n = cache->n_suffix_roots; const char* mime_type = NULL, *ret = NULL, *prev_suffix_pos = (const char*)-1; int fn_len, n_nodes; if( G_UNLIKELY( ! filename || ! *filename || 0 == n ) ) return NULL; if( cache->has_reverse_suffix ) /* since mime.cache ver: 1.1 */ { const char *suffix, *leaf_node, *_suffix_pos = (const char*)-1; fn_len = strlen( filename ); suffix = g_utf8_find_prev_char( filename, filename + fn_len ); leaf_node = lookup_reverse_suffix_nodes( cache->buffer, root, n, filename, suffix, &_suffix_pos ); if( leaf_node ) { mime_type = cache->buffer + VAL32( leaf_node, 4 ); /* g_debug( "found: %s", mime_type ); */ *suffix_pos = _suffix_pos; ret = mime_type; } } else /* before mime.cache ver: 1.1 */ { for( i = 0; i <n; ++i, root += 16 ) { guint32 first_child_off; guint32 ch = VAL32( root, 0 ); const char* suffix; suffix = strchr( filename, ch ); if( ! suffix ) continue; first_child_off = VAL32( root, 12 ); // FIXME: is this correct??? n = VAL32( root, 8 ); do{ mime_type = lookup_suffix_nodes( cache->buffer, cache->buffer + first_child_off, n, g_utf8_next_char(suffix) ); if( mime_type && suffix < prev_suffix_pos ) /* we want the longest suffix matched. */ { ret = mime_type; prev_suffix_pos = suffix; } }while( (suffix = strchr( suffix + 1, ch )) ); } *suffix_pos = ret ? prev_suffix_pos : (const char*)-1; } return ret; }
static void test_find (void) { /* U+0B0B Oriya Letter Vocalic R (\340\254\213) * U+10900 Phoenician Letter Alf (\360\220\244\200) * U+0041 Latin Capital Letter A (\101) * U+1EB6 Latin Capital Letter A With Breve And Dot Below (\341\272\266) */ const gchar *str = "\340\254\213\360\220\244\200\101\341\272\266\0\101"; const gchar *p = str + strlen (str); const gchar *q; q = g_utf8_find_prev_char (str, p); g_assert (q == str + 8); q = g_utf8_find_prev_char (str, q); g_assert (q == str + 7); q = g_utf8_find_prev_char (str, q); g_assert (q == str + 3); q = g_utf8_find_prev_char (str, q); g_assert (q == str); q = g_utf8_find_prev_char (str, q); g_assert (q == NULL); p = str + 2; q = g_utf8_find_next_char (p, NULL); g_assert (q == str + 3); q = g_utf8_find_next_char (q, NULL); g_assert (q == str + 7); q = g_utf8_find_next_char (p, str + 6); g_assert (q == str + 3); q = g_utf8_find_next_char (q, str + 6); g_assert (q == NULL); q = g_utf8_find_next_char (str, str); g_assert (q == NULL); q = g_utf8_find_next_char (str + strlen (str), NULL); g_assert (q == str + strlen (str) + 1); }
static gboolean move_back(GntBindable *bind, GList *null) { GntEntry *entry = GNT_ENTRY(bind); if (entry->cursor <= entry->start) return FALSE; entry->cursor = g_utf8_find_prev_char(entry->start, entry->cursor); if (entry->cursor < entry->scroll) entry->scroll = entry->cursor; update_kill_ring(entry, ENTRY_JAIL, NULL, 0); entry_redraw(GNT_WIDGET(entry)); return TRUE; }
void mosaic_search_box_remove_symbols (MosaicSearchBox *box, guint size) { gchar *text = g_strdup (mosaic_search_box_get_text (box)); if (strlen (text)) { gchar *p = text + strlen (text); for (int i = 0; i < size; i++) { p = g_utf8_find_prev_char (text, p); *p = '\0'; } mosaic_search_box_set_text (box, text); } g_free (text); }
static char * get_beginning_of_word(GntEntry *entry) { char *s = entry->cursor; while (s > entry->start) { char *t = g_utf8_find_prev_char(entry->start, s); if (isspace(*t)) break; s = t; } return s; }
/* Reverse suffix tree is used since mime.cache 1.1 (shared mime info 0.4) * Returns the address of the found "node", not mime-type. * FIXME: 1. Should be optimized with binary search * 2. Should consider weight of suffix nodes */ static const char* lookup_reverse_suffix_nodes( const char* buf, const char* nodes, guint32 n, const char* name, const char* suffix, const char** suffix_pos ) { const char *ret = NULL; const char *_suffix_pos = NULL, *cur_suffix_pos = (const char*)suffix + 1; const char* leaf_node = NULL; gunichar uchar; uchar = suffix ? g_unichar_tolower( g_utf8_get_char( suffix ) ) : 0; /* g_debug("%s: suffix= '%s'", name, suffix); */ int i; for( i = 0; i < n; ++i ) { const char* node =nodes + i * 12; guint32 ch = VAL32(node, 0); _suffix_pos = suffix; if( G_LIKELY( ch ) ) { if( ch == uchar ) { guint32 n_children = VAL32(node, 4); guint32 first_child_off = VAL32(node, 8); leaf_node = lookup_reverse_suffix_nodes( buf, buf + first_child_off, n_children, name, g_utf8_find_prev_char(name, suffix), &_suffix_pos ); if( leaf_node && _suffix_pos < cur_suffix_pos ) { ret = leaf_node; cur_suffix_pos = _suffix_pos; } } } else /* ch == 0 */ { /* guint32 weight = VAL32(node, 8); */ /* suffix is found in the tree! */ if( suffix < cur_suffix_pos ) { ret = node; cur_suffix_pos = suffix; } } } *suffix_pos = cur_suffix_pos; return ret; }
static gchar * video_sanitise_string (const gchar *str) { int i; gchar *line, *line_end; GRegex *regex; line = (gchar *) str; for (i = 0; video_blacklisted_prefix[i]; i++) { if (g_str_has_prefix (str, video_blacklisted_prefix[i])) { int len = strlen (video_blacklisted_prefix[i]); line = (gchar *) str + len; } } /* Get the substring limited by the first blacklisted word */ line_end = line + strlen (line); for (i = 0; video_blacklisted_words[i]; i++) { gchar *end; end = strcasestr (line, video_blacklisted_words[i]); if (end && end < line_end) { line_end = end; } } if (*line_end != '\0') { /* After removing substring with blacklisted word, ignore non alpha-numeric * char in the end of the sanitised string */ do { line_end = g_utf8_find_prev_char (line, line_end); } while (is_nonalnum (line_end)); /* If everything in the string is blacklisted, just ignore * the blackisting logic. */ if (line_end == NULL) { return g_strdup (str); } return g_strndup (line, line_end - line); } regex = g_regex_new ("\\.-\\.", 0, 0, NULL); line = g_regex_replace_literal(regex, line, -1, 0, ".", 0, NULL); g_regex_unref(regex); return line; }
static guint bastile_secure_buffer_real_insert_text (GtkEntryBuffer *buffer, guint position, const gchar *chars, guint n_chars) { BastileSecureBuffer *self = BASTILE_SECURE_BUFFER (buffer); BastileSecureBufferPrivate *pv = self->priv; gsize n_bytes; gsize at; n_bytes = g_utf8_offset_to_pointer (chars, n_chars) - chars; /* Need more memory */ if (n_bytes + pv->text_bytes + 1 > pv->text_size) { /* Calculate our new buffer size */ while (n_bytes + pv->text_bytes + 1 > pv->text_size) { if (pv->text_size == 0) { pv->text_size = MIN_SIZE; } else { if (2 * pv->text_size < GTK_ENTRY_BUFFER_MAX_SIZE) { pv->text_size *= 2; } else { pv->text_size = GTK_ENTRY_BUFFER_MAX_SIZE; if (n_bytes > pv->text_size - pv->text_bytes - 1) { n_bytes = pv->text_size - pv->text_bytes - 1; n_bytes = g_utf8_find_prev_char (chars, chars + n_bytes + 1) - chars; n_chars = g_utf8_strlen (chars, n_bytes); } break; } } } pv->text = mate_keyring_memory_realloc (pv->text, pv->text_size); } /* Actual text insertion */ at = g_utf8_offset_to_pointer (pv->text, position) - pv->text; g_memmove (pv->text + at + n_bytes, pv->text + at, pv->text_bytes - at); memcpy (pv->text + at, chars, n_bytes); /* Book keeping */ pv->text_bytes += n_bytes; pv->text_chars += n_chars; pv->text[pv->text_bytes] = '\0'; gtk_entry_buffer_emit_inserted_text (buffer, position, chars, n_chars); return n_chars; }
static gboolean move_back_word(GntBindable *bind, GList *null) { GntEntry *entry = GNT_ENTRY(bind); const char *iter = g_utf8_find_prev_char(entry->start, entry->cursor); if (iter < entry->start) return TRUE; iter = begin_word(iter, entry->start); entry->cursor = (char*)iter; if (entry->cursor < entry->scroll) entry->scroll = entry->cursor; update_kill_ring(entry, ENTRY_JAIL, NULL, 0); entry_redraw(GNT_WIDGET(bind)); return TRUE; }
void mosaic_search_box_kill_word (MosaicSearchBox *box) { const gchar *text = mosaic_search_box_get_text (box); gint size = strlen (text); if (size) { const gchar *p = text + size; int len = 0; while (p > text) { p = g_utf8_find_prev_char (text, p); gunichar c = g_utf8_get_char (p); if (g_unichar_isspace (c) && len > 0) break; len++; } mosaic_search_box_remove_symbols (box, len); } }
void str_rtrim(char *str) { int len = strlen(str); char *last = str + len; char *curr = last - 1; if (len == 0) return; while (*curr == ' ' || *curr == '\t' || *curr == '\r' || *curr == '\n') { last = curr; curr = g_utf8_find_prev_char(str, curr); if (curr == NULL) break; } *last = 0; }
gsize qof_strftime(gchar *buf, gsize max, const gchar *format, const struct tm *tm) { gsize convlen, retval; gchar *convbuf; g_return_val_if_fail(buf, 0); g_return_val_if_fail(max > 0, 0); g_return_val_if_fail(format, 0); g_return_val_if_fail(tm, 0); convbuf = qof_format_time(format, tm); if (!convbuf) { buf[0] = '\0'; return 0; } convlen = strlen(convbuf); if (max <= convlen) { /* Ensure only whole characters are copied into the buffer. */ gchar *end = g_utf8_find_prev_char(convbuf, convbuf + max); g_assert(end != NULL); convlen = end - convbuf; /* Return 0 because the buffer isn't large enough. */ retval = 0; } else { retval = convlen; } memcpy(buf, convbuf, convlen); buf[convlen] = '\0'; g_free(convbuf); return retval; }
gsize e_utf8_strftime_fix_am_pm (gchar *str, gsize max, const gchar *fmt, const struct tm *tm) { gsize sz, ret; gchar *locale_fmt, *buf; locale_fmt = g_locale_from_utf8 (fmt, -1, NULL, &sz, NULL); if (!locale_fmt) return 0; ret = e_strftime_fix_am_pm (str, max, locale_fmt, tm); if (!ret) { g_free (locale_fmt); return 0; } buf = g_locale_to_utf8 (str, ret, NULL, &sz, NULL); if (!buf) { g_free (locale_fmt); return 0; } if (sz >= max) { gchar *tmp = buf + max - 1; tmp = g_utf8_find_prev_char (buf, tmp); if (tmp) sz = tmp - buf; else sz = 0; } memcpy (str, buf, sz); str[sz] = '\0'; g_free (locale_fmt); g_free (buf); return sz; }
/* Determine whether there is whitespace to the left of the cursor. */ gboolean cmd_whitespace_to_left(struct cmdline* cmd, gchar* holdover) { gboolean result; if ( (cmd->pos == 0) || /* Kludge: if the shell buffer has a holdover, which consists only of a space, it's reasonable to assume it won't complete a sequence and will end up being added to the command line. */ (holdover && strlen(holdover) == 1 && *(holdover) == ' ') ) result = TRUE; else { if (cmd->is_utf8) { gchar* previous = g_utf8_find_prev_char( cmd->data->str, cmd->data->str + cmd->pos); result = previous && g_unichar_isspace(g_utf8_get_char(previous)); } else result = isspace( *(cmd->data->str + cmd->pos - 1) ); } return result; }
static void validate_and_insert (GeditDocumentOutputStream *stream, const gchar *buffer, gsize count) { GtkTextBuffer *text_buffer; GtkTextIter *iter; gsize len; text_buffer = GTK_TEXT_BUFFER (stream->priv->doc); iter = &stream->priv->pos; len = count; while (len != 0) { const gchar *end; gboolean valid; gsize nvalid; /* validate */ valid = g_utf8_validate (buffer, len, &end); nvalid = end - buffer; /* Note: this is a workaround for a 'bug' in GtkTextBuffer where inserting first a \r and then in a second insert, a \n, will result in two lines being added instead of a single one */ if (valid) { gchar *ptr; ptr = g_utf8_find_prev_char (buffer, buffer + len); if (ptr && *ptr == '\r' && ptr - buffer == len - 1) { stream->priv->buffer = g_new (gchar, 1); stream->priv->buffer[0] = '\r'; stream->priv->buflen = 1; /* Decrease also the len so in the check nvalid == len we get out of this method */ --nvalid; --len; } } /* if we've got any valid char we must tag the invalid chars */ if (nvalid > 0) { apply_error_tag (stream); } gtk_text_buffer_insert (text_buffer, iter, buffer, nvalid); /* If we inserted all return */ if (nvalid == len) { break; } buffer += nvalid; len = len - nvalid; if ((len < MAX_UNICHAR_LEN) && (g_utf8_get_char_validated (buffer, len) == (gunichar)-2)) { stream->priv->buffer = g_strndup (end, len); stream->priv->buflen = len; break; } /* we need the start of the chunk of invalid chars */ if (stream->priv->error_offset == -1) { stream->priv->error_offset = gtk_text_iter_get_offset (&stream->priv->pos); } insert_fallback (stream, buffer); ++buffer; --len; } }
static void rejilla_project_name_label_insert_text (GtkEditable *editable, const gchar *text, gint length, gint *position, gpointer NULL_data) { RejillaProjectNamePrivate *priv; const gchar *label; gchar *new_text; gint new_length; gchar *current; gint max_len; gchar *prev; gchar *next; priv = REJILLA_PROJECT_NAME_PRIVATE (editable); /* check if this new text will fit in 32 _bytes_ long buffer */ label = gtk_entry_get_text (GTK_ENTRY (editable)); max_len = 32 - strlen (label) - length; if (max_len >= 0) return; gdk_beep (); /* get the last character '\0' of the text to be inserted */ new_length = length; new_text = g_strdup (text); current = g_utf8_offset_to_pointer (new_text, g_utf8_strlen (new_text, -1)); /* don't just remove one character in case there was many more * that were inserted at the same time through DND, paste, ... */ prev = g_utf8_find_prev_char (new_text, current); if (!prev) { /* no more characters so no insertion */ g_signal_stop_emission_by_name (editable, "insert_text"); g_free (new_text); return; } do { next = current; current = prev; prev = g_utf8_find_prev_char (new_text, current); if (!prev) { /* no more characters so no insertion */ g_signal_stop_emission_by_name (editable, "insert_text"); g_free (new_text); return; } new_length -= next - current; max_len += next - current; } while (max_len < 0 && new_length > 0); *current = '\0'; g_signal_handlers_block_by_func (editable, (gpointer) rejilla_project_name_label_insert_text, NULL_data); gtk_editable_insert_text (editable, new_text, new_length, position); g_signal_handlers_unblock_by_func (editable, (gpointer) rejilla_project_name_label_insert_text, NULL_data); g_signal_stop_emission_by_name (editable, "insert_text"); g_free (new_text); }
static int key_action_tab_comp (GtkWidget *t, GdkEventKey *entry, char *d1, char *d2, struct session *sess) { int len = 0, elen = 0, i = 0, cursor_pos, ent_start = 0, comp = 0, prefix_len, skip_len = 0; gboolean is_nick = FALSE, is_cmd = FALSE, found = FALSE, has_nick_prefix = FALSE; char ent[CHANLEN], *postfix = NULL, *result, *ch; GList *list = NULL, *tmp_list = NULL; const char *text; GCompletion *gcomp = NULL; GString *buf; /* force the IM Context to reset */ SPELL_ENTRY_SET_EDITABLE (t, FALSE); SPELL_ENTRY_SET_EDITABLE (t, TRUE); text = SPELL_ENTRY_GET_TEXT (t); if (text[0] == 0) return 1; len = g_utf8_strlen (text, -1); /* must be null terminated */ cursor_pos = SPELL_ENTRY_GET_POS (t); /* handle "nick: " or "nick " or "#channel "*/ ch = g_utf8_find_prev_char(text, g_utf8_offset_to_pointer(text,cursor_pos)); if (ch && ch[0] == ' ') { skip_len++; ch = g_utf8_find_prev_char(text, ch); if (!ch) return 2; cursor_pos = g_utf8_pointer_to_offset(text, ch); if (cursor_pos && (g_utf8_get_char_validated(ch, -1) == ':' || g_utf8_get_char_validated(ch, -1) == ',' || g_utf8_get_char_validated (ch, -1) == g_utf8_get_char_validated (prefs.hex_completion_suffix, -1))) { skip_len++; } else cursor_pos = g_utf8_pointer_to_offset(text, g_utf8_offset_to_pointer(ch, 1)); } comp = skip_len; /* store the text following the cursor for reinsertion later */ if ((cursor_pos + skip_len) < len) postfix = g_utf8_offset_to_pointer(text, cursor_pos + skip_len); for (ent_start = cursor_pos; ; --ent_start) { if (ent_start == 0) break; ch = g_utf8_offset_to_pointer(text, ent_start - 1); if (ch && ch[0] == ' ') break; } if (ent_start == 0 && text[0] == prefs.hex_input_command_char[0]) { ent_start++; is_cmd = TRUE; } else if (strchr (sess->server->chantypes, text[ent_start]) == NULL) { is_nick = TRUE; if (strchr (sess->server->nick_prefixes, text[ent_start]) != NULL) { if (ent_start == 0) has_nick_prefix = TRUE; ent_start++; } } prefix_len = ent_start; elen = cursor_pos - ent_start; g_utf8_strncpy (ent, g_utf8_offset_to_pointer (text, prefix_len), elen); if (sess->type == SESS_DIALOG && is_nick) { /* tab in a dialog completes the other person's name */ if (rfc_ncasecmp (sess->channel, ent, elen) == 0) { result = sess->channel; is_nick = FALSE; } else return 2; } else { if (is_nick) { gcomp = g_completion_new((GCompletionFunc)gcomp_nick_func); tmp_list = userlist_double_list(sess); /* create a temp list so we can free the memory */ if (prefs.hex_completion_sort == 1) /* sort in last-talk order? */ tmp_list = g_list_sort (tmp_list, (void *)talked_recent_cmp); } else { gcomp = g_completion_new (NULL); if (is_cmd) { tmp_list = cmdlist_double_list (command_list); for(i = 0; xc_cmds[i].name != NULL ; i++) { tmp_list = g_list_prepend (tmp_list, xc_cmds[i].name); } tmp_list = plugin_command_list(tmp_list); } else tmp_list = chanlist_double_list (sess_list); } tmp_list = g_list_reverse(tmp_list); /* make the comp entries turn up in the right order */ g_completion_set_compare (gcomp, (GCompletionStrncmpFunc)rfc_ncasecmp); if (tmp_list) { g_completion_add_items (gcomp, tmp_list); g_list_free (tmp_list); } if (comp && !(rfc_ncasecmp(old_gcomp.data, ent, old_gcomp.elen) == 0)) { key_action_tab_clean (); comp = 0; } list = g_completion_complete_utf8 (gcomp, comp ? old_gcomp.data : ent, &result); if (result == NULL) /* No matches found */ { g_completion_free(gcomp); return 2; } if (comp) /* existing completion */ { while(list) /* find the current entry */ { if(rfc_ncasecmp(list->data, ent, elen) == 0) { found = TRUE; break; } list = list->next; } if (found) { if (!(d1 && d1[0])) /* not holding down shift */ { if (g_list_next(list) == NULL) list = g_list_first(list); else list = g_list_next(list); } else { if (g_list_previous(list) == NULL) list = g_list_last(list); else list = g_list_previous(list); } g_free(result); result = (char*)list->data; } else { g_free(result); g_completion_free(gcomp); return 2; } } else { strcpy(old_gcomp.data, ent); old_gcomp.elen = elen; /* Get the first nick and put out the data for future nickcompletes */ if (prefs.hex_completion_amount > 0 && g_list_length (list) <= (guint) prefs.hex_completion_amount) { g_free(result); result = (char*)list->data; } else { /* bash style completion */ if (g_list_next(list) != NULL) { buf = g_string_sized_new (MAX(COMP_BUF, len + NICKLEN)); if (strlen (result) > elen) /* the largest common prefix is larger than nick, change the data */ { if (prefix_len) g_string_append_len (buf, text, offset_to_len (text, prefix_len)); g_string_append (buf, result); cursor_pos = buf->len; g_free(result); if (postfix) { g_string_append_c (buf, ' '); g_string_append (buf, postfix); } SPELL_ENTRY_SET_TEXT (t, buf->str); SPELL_ENTRY_SET_POS (t, len_to_offset (buf->str, cursor_pos)); g_string_erase (buf, 0, -1); } else g_free(result); while (list) { len = buf->len; elen = strlen (list->data); /* next item to add */ if (len + elen + 2 >= COMP_BUF) /* +2 is space + null */ { PrintText (sess, buf->str); g_string_erase (buf, 0, -1); } g_string_append (buf, (char*)list->data); g_string_append_c (buf, ' '); list = list->next; } PrintText (sess, buf->str); g_completion_free(gcomp); g_string_free (buf, TRUE); return 2; } /* Only one matching entry */ g_free(result); result = list->data; } } } if(result) { buf = g_string_sized_new (len + NICKLEN); if (prefix_len) g_string_append_len (buf, text, offset_to_len (text, prefix_len)); g_string_append (buf, result); if((!prefix_len || has_nick_prefix) && is_nick && prefs.hex_completion_suffix[0] != '\0') g_string_append_unichar (buf, g_utf8_get_char_validated (prefs.hex_completion_suffix, -1)); g_string_append_c (buf, ' '); cursor_pos = buf->len; if (postfix) g_string_append (buf, postfix); SPELL_ENTRY_SET_TEXT (t, buf->str); SPELL_ENTRY_SET_POS (t, len_to_offset (buf->str, cursor_pos)); g_string_free (buf, TRUE); } if (gcomp) g_completion_free(gcomp); return 2; }