static void input_prev_word(void) { bool word_skipped = false; while(pos > 0) { input_move_left(false); const int c = get_char(&input_buffer[pos], encoding); if (ne_isword(c, encoding)) word_skipped = true; else if (word_skipped) { input_move_right(false); break; } } input_refresh(); }
static void input_next_word(void) { bool space_skipped = false; while(pos < len) { const int c = get_char(&input_buffer[pos], encoding); if (!ne_isword(c, encoding)) space_skipped = true; else if (space_skipped) break; input_move_right(false); } if (x == ne_columns - 1) { offset = pos; x = start_x; } input_refresh(); }
static void search_buff(const buffer *b, char * p, const int encoding, const bool case_search, const int ext) { assert(p); const int p_len = strlen(p); const int (*cmp)(const char *, const char *, size_t) = case_search ? strncmp : strncasecmp; for(line_desc *ld = (line_desc *)b->line_desc_list.head, *next; next = (line_desc *)ld->ld_node.next; ld = next) { int64_t l = 0, r = 0; do { /* find left edge of word */ while (l < ld->line_len - p_len && !ne_isword(get_char(&ld->line[l], b->encoding), b->encoding)) l += get_char_width(&ld->line[l], b->encoding); if (l < ld->line_len - p_len ) { int ch; /* find right edge of word */ r = l + get_char_width(&ld->line[l], b->encoding); /* accept "'" as a word character if it is followed by another word character, so that words like "don't" are not broken into "don" and "t". */ while (r < ld->line_len && ( ne_isword(ch=get_char(&ld->line[r], b->encoding), b->encoding) || ( r+1 < ld->line_len && ch == '\'' && ne_isword(get_char(&ld->line[r+1], b->encoding), b->encoding)) ) ) r += get_char_width(&ld->line[r], b->encoding); if ((b != cur_buffer || ld != b->cur_line_desc || b->cur_pos < l || r < b->cur_pos) && r - l > p_len && (b->encoding == encoding || is_ascii(&ld->line[l], r - l)) && !cmp(p, &ld->line[l], p_len)) add_string(&ld->line[l], r - l, ext); l = r; count_scanned++; } assert(l <= ld->line_len); if (stop || count_scanned >= MAX_AUTOCOMPLETE_SCAN) { add_string(NULL, -1, 0); return; } } while (l < ld->line_len - p_len); } add_string(NULL, -1, 0); }
static void input_autocomplete(void) { int dx = 0, prefix_pos = pos; char *p; /* find a usable prefix */ if (prefix_pos && prefix_pos <= len) { prefix_pos = prev_pos(input_buffer, prefix_pos, encoding); dx--; while (prefix_pos && ne_isword(get_char(&input_buffer[prefix_pos], encoding), encoding)) { dx--; prefix_pos = prev_pos(input_buffer, prefix_pos, encoding); } if (! ne_isword(get_char(&input_buffer[prefix_pos], encoding), encoding)) { dx++; prefix_pos = next_pos(input_buffer, prefix_pos, encoding); } p = malloc(pos - prefix_pos + 1); if (!p) { alert(); /* OUT_OF_MEMORY */ return; } strncpy(p, &input_buffer[prefix_pos], pos - prefix_pos); } else p = malloc(1); /* no prefix left of the cursor; we'll give an empty one. */ p[pos - prefix_pos] = 0; int ac_err; if (p = autocomplete(p, NULL, true, &ac_err)) { encoding_type ac_encoding = detect_encoding(p, strlen(p)); if (ac_encoding != ENC_ASCII && encoding != ENC_ASCII && ac_encoding != encoding) { free(p); alert(); } else { encoding = ac_encoding; if (prefix_pos < pos) { memmove(&input_buffer[prefix_pos], &input_buffer[pos], len - pos + 1); len -= pos - prefix_pos; pos = prefix_pos; } int ac_len = strlen(p); if (ac_len + len >= MAX_INPUT_LINE_LEN) ac_len = MAX_INPUT_LINE_LEN - len; memmove(&input_buffer[pos + ac_len], &input_buffer[pos], len - pos + 1); memmove(&input_buffer[pos], p, ac_len); len += ac_len; while (ac_len > 0) { const int cw = get_char_width(&input_buffer[pos],encoding); pos = next_pos(input_buffer, pos, encoding); ac_len -= cw; dx++; } free(p); x += dx; if (x >= ne_columns) { dx = x - ne_columns + 1; while (dx--) { offset = next_pos(input_buffer, offset, encoding); } x = ne_columns - 1; } } } if (ac_err == AUTOCOMPLETE_COMPLETED || ac_err == AUTOCOMPLETE_CANCELLED) { do_action(cur_buffer, REFRESH_A, 0, NULL); refresh_window(cur_buffer); set_attr(0); print_prompt(NULL); } input_refresh(); }
static int to_something(buffer *b, int (to_first)(int), int (to_rest)(int)) { assert_buffer(b); /* If we are after the end of the line, just return ERROR. */ if (b->cur_line == b->num_lines -1 && b->cur_pos >= b->cur_line_desc->line_len) return ERROR; int64_t pos = b->cur_pos; int c; /* First of all, we search for the word start, if we're not over it. */ if (pos >= b->cur_line_desc->line_len || !ne_isword(c = get_char(&b->cur_line_desc->line[pos], b->encoding), b->encoding)) if (search_word(b, 1) != OK) return ERROR; bool changed = false; int64_t new_len = 0; pos = b->cur_pos; const int64_t cur_char = b->cur_char; const int cur_x = b->cur_x; /* Then, we compute the word position extremes, length of the result (which may change because of casing). */ while (pos < b->cur_line_desc->line_len && ne_isword(c = get_char(&b->cur_line_desc->line[pos], b->encoding), b->encoding)) { const int new_c = new_len ? to_rest(c) : to_first(c); changed |= (c != new_c); if (b->encoding == ENC_UTF8) new_len += utf8seqlen(new_c); else new_len++; pos = next_pos(b->cur_line_desc->line, pos, b->encoding); } const int64_t len = pos - b->cur_pos; if (!len) { char_right(b); return OK; } if (changed) { /* We actually perform changes only if some character was case folded. */ char * word = malloc(new_len * sizeof *word); if (!word) return OUT_OF_MEMORY; pos = b->cur_pos; new_len = 0; /* Second pass: we actually build the transformed word. */ while (pos < b->cur_line_desc->line_len && ne_isword(c = get_char(&b->cur_line_desc->line[pos], b->encoding), b->encoding)) { if (b->encoding == ENC_UTF8) new_len += utf8str(new_len ? to_rest(c) : to_first(c), word + new_len); else { word[new_len] = new_len ? to_rest(c) : to_first(c); new_len++; } pos = next_pos(b->cur_line_desc->line, pos, b->encoding); } start_undo_chain(b); delete_stream(b, b->cur_line_desc, b->cur_line, b->cur_pos, len); if (new_len) insert_stream(b, b->cur_line_desc, b->cur_line, b->cur_pos, word, new_len); free(word); end_undo_chain(b); if (cur_char < b->attr_len) b->attr_len = cur_char; update_line(b, b->cur_line_desc, b->cur_y, cur_x, false); need_attr_update = true; } return search_word(b, 1); }