[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemacs-commit] qemacs Makefile qe.h qe.c search.c
From: |
Charlie Gordon |
Subject: |
[Qemacs-commit] qemacs Makefile qe.h qe.c search.c |
Date: |
Mon, 17 Aug 2015 16:56:49 +0000 |
CVSROOT: /sources/qemacs
Module name: qemacs
Changes by: Charlie Gordon <chqrlie> 15/08/17 16:56:49
Modified files:
. : Makefile qe.h qe.c
Added files:
. : search.c
Log message:
search: split search code from qe.c into new module search.c
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/qemacs/Makefile?cvsroot=qemacs&r1=1.78&r2=1.79
http://cvs.savannah.gnu.org/viewcvs/qemacs/qe.h?cvsroot=qemacs&r1=1.198&r2=1.199
http://cvs.savannah.gnu.org/viewcvs/qemacs/qe.c?cvsroot=qemacs&r1=1.201&r2=1.202
http://cvs.savannah.gnu.org/viewcvs/qemacs/search.c?cvsroot=qemacs&rev=1.1
Patches:
Index: Makefile
===================================================================
RCS file: /sources/qemacs/qemacs/Makefile,v
retrieving revision 1.78
retrieving revision 1.79
diff -u -b -r1.78 -r1.79
--- Makefile 7 Aug 2015 08:28:59 -0000 1.78
+++ Makefile 17 Aug 2015 16:56:48 -0000 1.79
@@ -63,8 +63,8 @@
TARGETLIBS:=
TARGETS+= qe$(EXE) tqe$(EXE) kmaps ligatures
-OBJS:= qe.o parser.o charset.o buffer.o input.o display.o util.o hex.o \
- list.o cutils.o
+OBJS:= qe.o util.o cutils.o charset.o buffer.o search.o parser.o input.o
display.o hex.o \
+ list.o
TOBJS:= $(OBJS)
OBJS+= extras.o variables.o
Index: qe.h
===================================================================
RCS file: /sources/qemacs/qemacs/qe.h,v
retrieving revision 1.198
retrieving revision 1.199
diff -u -b -r1.198 -r1.199
--- qe.h 16 Aug 2015 23:15:02 -0000 1.198
+++ qe.h 17 Aug 2015 16:56:48 -0000 1.199
@@ -1880,6 +1880,7 @@
void do_scroll_left_right(EditState *s, int dir);
void do_scroll_up_down(EditState *s, int dir);
void perform_scroll_up_down(EditState *s, int h);
+void do_center_cursor_maybe(EditState *s);
void do_center_cursor(EditState *s);
void do_quote(EditState *s, int argval);
void do_overwrite_mode(EditState *s, int argval);
@@ -1962,7 +1963,6 @@
void window_resize(EditState *s, int target_w, int target_h);
void wheel_scroll_up_down(EditState *s, int dir);
void qe_mouse_event(QEEvent *ev);
-int parse_command_line(int argc, char **argv);
void set_user_option(const char *user);
void set_tty_charset(const char *name);
Index: qe.c
===================================================================
RCS file: /sources/qemacs/qemacs/qe.c,v
retrieving revision 1.201
retrieving revision 1.202
diff -u -b -r1.201 -r1.202
--- qe.c 16 Aug 2015 23:15:01 -0000 1.201
+++ qe.c 17 Aug 2015 16:56:49 -0000 1.202
@@ -1187,7 +1187,7 @@
}
/* center window if offset is not currently visible */
-static void do_center_cursor_maybe(EditState *s)
+void do_center_cursor_maybe(EditState *s)
{
if (s->offset < s->offset_top
|| (s->offset_bottom >= 0 && s->offset >= s->offset_bottom)) {
@@ -6455,777 +6455,6 @@
qe_free(&reply);
}
-/* Search stuff */
-
-#define SEARCH_FLAG_SMARTCASE 0x0001 /* case fold unless upper case present
*/
-#define SEARCH_FLAG_IGNORECASE 0x0002
-#define SEARCH_FLAG_WORD 0x0004
-#define SEARCH_FLAG_WRAPPED 0x0008
-#define SEARCH_FLAG_HEX 0x0010
-#define SEARCH_FLAG_UNIHEX 0x0020
-
-/* XXX: OPTIMIZE ! */
-static int eb_search(EditBuffer *b, int start_offset, int dir, int flags,
- const unsigned int *buf, int len,
- CSSAbortFunc *abort_func, void *abort_opaque,
- int *found_offset, int *found_end)
-{
- int total_size = b->total_size;
- int c, c2, offset = start_offset, offset1, offset2, offset3, pos;
-
- if (len == 0)
- return 0;
-
- *found_offset = -1;
- *found_end = -1;
-
- /* analyze buffer if smart case */
- if (flags & SEARCH_FLAG_SMARTCASE) {
- int upper_count = 0;
- int lower_count = 0;
- for (pos = 0; pos < len; pos++) {
- lower_count += qe_islower(buf[pos]);
- upper_count += qe_isupper(buf[pos]);
- }
- if (lower_count > 0 && upper_count == 0)
- flags |= SEARCH_FLAG_IGNORECASE;
- }
-
- if (flags & SEARCH_FLAG_HEX) {
- /* handle buffer as single bytes */
- /* XXX: should handle ucs2 and ucs4 as words */
- for (;; (void)(dir >= 0 && offset++)) {
- if (dir < 0) {
- if (offset == 0)
- return 0;
- offset--;
- }
- if (offset >= total_size)
- return 0;
-
- if ((offset & 0xfffff) == 0) {
- /* check for search abort every megabyte */
- if (abort_func && abort_func(abort_opaque))
- return -1;
- }
-
- pos = 0;
- for (offset2 = offset; offset2 < total_size;) {
- /* CG: Should bufferize a bit ? */
- c = eb_read_one_byte(b, offset2++);
- c2 = buf[pos++];
- if (c != c2)
- break;
- if (pos >= len) {
- /* check end of word */
- *found_offset = offset;
- *found_end = offset2;
- return 1;
- }
- }
- }
- }
-
- for (offset1 = offset;;) {
- if (dir < 0) {
- if (offset == 0)
- return 0;
- eb_prevc(b, offset, &offset);
- } else {
- offset = offset1;
- if (offset >= total_size)
- return 0;
- }
- if ((offset & 0xfffff) == 0) {
- /* check for search abort every megabyte */
- if (abort_func && abort_func(abort_opaque))
- return -1;
- }
-
- if (flags & SEARCH_FLAG_WORD) {
- /* check for start of word */
- c = eb_prevc(b, offset, &offset3);
- if (qe_isword(c))
- continue;
- }
-
- /* CG: XXX: Should use buffer specific accelerator */
- /* Get first char separately to compute offset1 */
- c = eb_nextc(b, offset, &offset1);
-
- pos = 0;
- for (offset2 = offset1;;) {
- c2 = buf[pos++];
- if (flags & SEARCH_FLAG_IGNORECASE) {
- if (qe_toupper(c) != qe_toupper(c2))
- break;
- } else {
- if (c != c2)
- break;
- }
- if (pos >= len) {
- if (flags & SEARCH_FLAG_WORD) {
- /* check for end of word */
- c = eb_nextc(b, offset2, &offset3);
- if (qe_isword(c))
- break;
- }
- if (dir > 0 || offset2 <= start_offset) {
- *found_offset = offset;
- *found_end = offset2;
- return 1;
- }
- }
- if (offset2 >= total_size)
- break;
- c = eb_nextc(b, offset2, &offset2);
- }
- }
-}
-
-/* should separate search string length and number of match positions */
-#define SEARCH_LENGTH 256
-#define FOUND_TAG 0x80000000
-#define FOUND_REV 0x40000000
-
-/* store last searched string */
-static unsigned int last_search_u32[SEARCH_LENGTH];
-static int last_search_u32_len = 0;
-
-static int search_abort_func(__unused__ void *opaque)
-{
- return is_user_input_pending();
-}
-
-typedef struct ISearchState {
- EditState *s;
- int saved_mark;
- int start_offset;
- int start_dir;
- int quoting;
- int dir;
- int pos;
- int search_flags;
- int found_offset, found_end;
- unsigned int search_u32[SEARCH_LENGTH];
-} ISearchState;
-
-static void buf_encode_search_u32(buf_t *out, const unsigned int *str, int len)
-{
- int i;
-
- for (i = 0; i < len; i++) {
- unsigned int v = str[i];
- if (!(v & FOUND_TAG)) {
- if (v < 32 || v == 127) {
- buf_printf(out, "^%c", (v + '@') & 127);
- } else {
- buf_putc_utf8(out, v);
- }
- if (buf_avail(out) <= 0)
- break;
- }
- }
-}
-
-static void buf_encode_search_str(buf_t *out, const char *str)
-{
- while (*str) {
- int c = utf8_decode(&str);
- if (c < 32 || c == 127) {
- buf_printf(out, "^%c", (c + '@') & 127);
- } else {
- buf_putc_utf8(out, c);
- }
- if (buf_avail(out) <= 0)
- break;
- }
-}
-
-static void isearch_display(ISearchState *is)
-{
- EditState *s = is->s;
- char ubuf[256];
- buf_t outbuf, *out;
- unsigned int buf[SEARCH_LENGTH];
- int c, i, len, hex_nibble, max_nibble, h, hc;
- unsigned int v;
- int search_offset, flags, dir = is->start_dir;
-
- /* prepare the search bytes */
- len = 0;
- search_offset = is->start_offset;
- max_nibble = hex_nibble = hc = 0;
- flags = is->search_flags;
- if (flags & SEARCH_FLAG_UNIHEX)
- max_nibble = 6;
- if (flags & SEARCH_FLAG_HEX)
- max_nibble = 2;
-
- for (i = 0; i < is->pos; i++) {
- v = is->search_u32[i];
- if (v & FOUND_TAG) {
- dir = (v & FOUND_REV) ? -1 : 1;
- search_offset = v & ~(FOUND_TAG | FOUND_REV);
- continue;
- }
- c = v;
- if (len < countof(buf)) {
- if (max_nibble) {
- h = to_hex(c);
- if (h >= 0) {
- hc = (hc << 4) | h;
- if (++hex_nibble == max_nibble) {
- buf[len++] = hc;
- hex_nibble = hc = 0;
- }
- } else {
- if (c == ' ' && hex_nibble) {
- buf[len++] = hc;
- hex_nibble = hc = 0;
- }
- }
- } else {
- buf[len++] = c;
- }
- }
- }
- if (hex_nibble >= 2) {
- buf[len++] = hc;
- hex_nibble = hc = 0;
- }
-
- is->dir = dir;
-
- if (len == 0) {
- s->b->mark = is->saved_mark;
- s->offset = is->start_offset;
- s->region_style = 0;
- is->found_offset = -1;
- } else {
- if (eb_search(s->b, search_offset, is->dir, flags,
- buf, len, search_abort_func, NULL,
- &is->found_offset, &is->found_end) > 0) {
- s->region_style = QE_STYLE_SEARCH_MATCH;
- if (is->dir > 0) {
- s->b->mark = is->found_offset;
- s->offset = is->found_end;
- } else {
- s->b->mark = is->found_end;
- s->offset = is->found_offset;
- }
- }
- }
-
- /* display search string */
- out = buf_init(&outbuf, ubuf, sizeof(ubuf));
- if (is->found_offset < 0 && len > 0)
- buf_puts(out, "Failing ");
- else
- if (is->search_flags & SEARCH_FLAG_WRAPPED) {
- buf_puts(out, "Wrapped ");
- is->search_flags &= ~SEARCH_FLAG_WRAPPED;
- }
- if (is->search_flags & SEARCH_FLAG_UNIHEX)
- buf_puts(out, "Unihex ");
- if (is->search_flags & SEARCH_FLAG_HEX)
- buf_puts(out, "Hex ");
- if (is->search_flags & SEARCH_FLAG_WORD)
- buf_puts(out, "Word ");
- if (is->search_flags & SEARCH_FLAG_IGNORECASE)
- buf_puts(out, "Folding ");
- else
- if (!(is->search_flags & SEARCH_FLAG_SMARTCASE))
- buf_puts(out, "Exact ");
-
- buf_puts(out, "I-search");
- if (is->dir < 0)
- buf_puts(out, " backward");
- buf_puts(out, ": ");
- buf_encode_search_u32(out, is->search_u32, is->pos);
- if (is->quoting)
- buf_puts(out, "^Q-");
-
- /* display text */
- do_center_cursor_maybe(s);
- edit_display(s->qe_state);
- put_status(NULL, "%s", out->buf);
- dpy_flush(s->screen);
-}
-
-static int isearch_grab(ISearchState *is, EditBuffer *b, int from, int to)
-{
- int offset, c, last = is->pos;
- if (b) {
- if (to < 0 || to > b->total_size)
- to = b->total_size;
- for (offset = from; is->pos < SEARCH_LENGTH && offset < to;) {
- c = eb_nextc(b, offset, &offset);
- is->search_u32[is->pos++] = c;
- }
- }
- return is->pos - last;
-}
-
-static void isearch_key(void *opaque, int ch)
-{
- ISearchState *is = opaque;
- EditState *s = is->s;
- QEmacsState *qs = &qe_state;
- int i, j, offset0, offset1, curdir = is->dir;
- int emacs_behaviour = !qs->emulation_flags;
-
- if (is->quoting) {
- is->quoting = 0;
- if (!KEY_IS_SPECIAL(ch))
- goto addch;
- }
- /* XXX: all these should be isearch-mode bindings */
- switch (ch) {
- case KEY_DEL:
- case KEY_BS:
- if (is->pos > 0)
- is->pos--;
- break;
- case KEY_CTRL('g'):
- s->b->mark = is->saved_mark;
- s->offset = is->start_offset;
- s->region_style = 0;
- put_status(s, "Quit");
- the_end:
- /* save current searched string */
- if (is->pos > 0) {
- j = 0;
- for (i = 0; i < is->pos; i++) {
- if (!(is->search_u32[i] & FOUND_TAG))
- last_search_u32[j++] = is->search_u32[i];
- }
- last_search_u32_len = j;
- }
- qe_ungrab_keys();
- qe_free(&is);
- edit_display(s->qe_state);
- dpy_flush(s->screen);
- return;
- case KEY_CTRL('s'): /* next match */
- is->dir = 1;
- goto addpos;
- case KEY_CTRL('r'): /* previous match */
- is->dir = -1;
- addpos:
- /* use last seached string if no input */
- if (is->pos == 0 && is->dir == curdir) {
- memcpy(is->search_u32, last_search_u32,
- last_search_u32_len * sizeof(*is->search_u32));
- is->pos = last_search_u32_len;
- } else
- if (is->pos < SEARCH_LENGTH) {
- /* add the match position, if any */
- unsigned long v = is->dir > 0 ? FOUND_TAG : FOUND_TAG | FOUND_REV;
- if (is->found_offset < 0) {
- is->search_flags |= SEARCH_FLAG_WRAPPED;
- if (is->dir < 0)
- v |= s->b->total_size;
- } else {
- v |= s->offset;
- }
- is->search_u32[is->pos++] = v;
- }
- break;
- case KEY_CTRL('q'):
- is->quoting = 1;
- break;
- case KEY_META('w'):
- emacs_behaviour ^= 1;
- /* fall thru */
- case KEY_CTRL('w'):
- if (emacs_behaviour) {
- /* grab word at cursor */
- offset0 = s->offset;
- do_word_right(s, 1);
- offset1 = s->offset;
- s->offset = offset0;
- isearch_grab(is, s->b, offset0, offset1);
- } else {
- /* toggle word match */
- is->search_flags ^= SEARCH_FLAG_WORD;
- }
- break;
- case KEY_META('y'):
- emacs_behaviour ^= 1;
- /* fall thru */
- case KEY_CTRL('y'):
- if (emacs_behaviour) {
- /* grab line at cursor */
- offset0 = s->offset;
- if (eb_nextc(s->b, offset0, &offset1) == '\n')
- offset0 = offset1;
- do_eol(s);
- offset1 = s->offset;
- s->offset = offset0;
- isearch_grab(is, s->b, offset0, offset1);
- } else {
- /* yank into search string */
- isearch_grab(is, qs->yank_buffers[qs->yank_current], 0, -1);
- }
- break;
- case KEY_META('b'):
- case KEY_CTRL('b'):
- /* cycle unihex, hex, normal search */
- if (is->search_flags & SEARCH_FLAG_UNIHEX)
- is->search_flags ^= SEARCH_FLAG_HEX | SEARCH_FLAG_UNIHEX;
- else
- if (is->search_flags & SEARCH_FLAG_HEX)
- is->search_flags ^= SEARCH_FLAG_HEX;
- else
- is->search_flags ^= SEARCH_FLAG_UNIHEX;
- break;
- case KEY_META('c'):
- case KEY_CTRL('c'):
- /* toggle case sensitivity */
- if (is->search_flags & (SEARCH_FLAG_IGNORECASE |
SEARCH_FLAG_SMARTCASE)) {
- is->search_flags &= ~SEARCH_FLAG_IGNORECASE;
- } else {
- is->search_flags |= SEARCH_FLAG_IGNORECASE;
- }
- is->search_flags &= ~SEARCH_FLAG_SMARTCASE;
- break;
- case KEY_CTRL('l'):
- do_center_cursor(s);
- break;
- default:
- if ((KEY_IS_SPECIAL(ch) || KEY_IS_CONTROL(ch)) && ch != '\t') {
- /* exit search mode */
-#if 0
- // FIXME: behaviour from qemacs-0.3pre13
- if (is->found_offset >= 0) {
- s->b->mark = is->found_offset;
- } else {
- s->b->mark = is->start_offset;
- }
- put_status(s, "Marked");
-#endif
- s->b->mark = is->start_offset;
- s->region_style = 0;
- put_status(s, "Mark saved where search started");
- /* repost key */
- if (ch != KEY_RET)
- unget_key(ch);
- goto the_end;
- } else {
- addch:
- if (is->pos < SEARCH_LENGTH) {
- is->search_u32[is->pos++] = ch;
- }
- }
- break;
- }
- isearch_display(is);
-}
-
-/* XXX: handle busy */
-void do_isearch(EditState *s, int dir)
-{
- ISearchState *is;
- int flags = SEARCH_FLAG_SMARTCASE;
-
- is = qe_mallocz(ISearchState);
- if (!is)
- return;
- is->s = s;
- is->saved_mark = s->b->mark;
- is->start_offset = s->offset;
- is->start_dir = is->dir = dir;
- is->pos = 0;
- if (s->hex_mode) {
- if (s->unihex_mode)
- flags |= SEARCH_FLAG_UNIHEX;
- else
- flags |= SEARCH_FLAG_HEX;
- }
- is->search_flags = flags;
-
- qe_grab_keys(isearch_key, is);
- isearch_display(is);
-}
-
-static int search_to_u32(unsigned int *buf, int size,
- const char *str, int flags)
-{
- if (flags & (SEARCH_FLAG_HEX | SEARCH_FLAG_UNIHEX)) {
- /* CG: XXX: Should mix utf8 and hex syntax in hex modes */
- const char *s;
- int c, hex_nibble, max_nibble, h, hc, len;
-
- max_nibble = (flags & SEARCH_FLAG_UNIHEX) ? 6 : 2;
- s = str;
- hex_nibble = hc = 0;
- for (len = 0; len < size;) {
- c = *s++;
- if (c == '\0') {
- if (hex_nibble >= 2) {
- buf[len++] = hc;
- hex_nibble = hc = 0;
- }
- break;
- }
- h = to_hex(c);
- if (h >= 0) {
- hc = (hc << 4) | h;
- if (++hex_nibble == max_nibble) {
- buf[len++] = hc;
- hex_nibble = hc = 0;
- }
- } else {
- if (c == ' ' && hex_nibble) {
- buf[len++] = hc;
- hex_nibble = hc = 0;
- }
- }
- }
- return len;
- } else {
- return utf8_to_unicode(buf, size, str);
- }
-}
-
-typedef struct QueryReplaceState {
- EditState *s;
- int start_offset;
- int search_flags;
- int replace_all;
- int nb_reps;
- int search_u32_len, replace_u32_len;
- int found_offset, found_end;
- int last_offset;
- char search_str[SEARCH_LENGTH]; /* may be in hex */
- char replace_str[SEARCH_LENGTH]; /* may be in hex */
- unsigned int search_u32[SEARCH_LENGTH]; /* code points */
- unsigned int replace_u32[SEARCH_LENGTH]; /* code points */
-} QueryReplaceState;
-
-static void query_replace_abort(QueryReplaceState *is)
-{
- EditState *s = is->s;
-
- qe_ungrab_keys();
- s->b->mark = is->start_offset;
- s->region_style = 0;
- put_status(NULL, "Replaced %d occurrences", is->nb_reps);
- qe_free(&is);
- edit_display(s->qe_state);
- dpy_flush(&global_screen);
-}
-
-static void query_replace_replace(QueryReplaceState *is)
-{
- EditState *s = is->s;
-
- /* XXX: handle smart case replacement */
- is->nb_reps++;
- eb_delete(s->b, is->found_offset, is->found_end - is->found_offset);
- is->found_offset += eb_insert_u32_buf(s->b, is->found_offset,
- is->replace_u32, is->replace_u32_len);
-}
-
-static void query_replace_display(QueryReplaceState *is)
-{
- EditState *s = is->s;
- char ubuf[256];
- buf_t outbuf, *out;
-
- is->last_offset = is->found_offset;
- is->search_u32_len = search_to_u32(is->search_u32,
- countof(is->search_u32),
- is->search_str, is->search_flags);
- is->replace_u32_len = search_to_u32(is->replace_u32,
- countof(is->replace_u32),
- is->replace_str, is->search_flags);
-
- for (;;) {
- if (eb_search(s->b, is->found_offset, 1, is->search_flags,
- is->search_u32, is->search_u32_len,
- NULL, NULL, &is->found_offset, &is->found_end) <= 0) {
- query_replace_abort(is);
- return;
- }
- if (is->replace_all) {
- query_replace_replace(is);
- continue;
- }
- break;
- }
- /* display prompt string */
- out = buf_init(&outbuf, ubuf, sizeof(ubuf));
- if (is->search_flags & SEARCH_FLAG_UNIHEX)
- buf_puts(out, "Unihex ");
- if (is->search_flags & SEARCH_FLAG_HEX)
- buf_puts(out, "Hex ");
- if (is->search_flags & SEARCH_FLAG_WORD)
- buf_puts(out, "Word ");
- if (is->search_flags & SEARCH_FLAG_IGNORECASE)
- buf_puts(out, "Folding ");
- else
- if (!(is->search_flags & SEARCH_FLAG_SMARTCASE))
- buf_puts(out, "Exact ");
-
- buf_puts(out, "Query replace ");
- buf_encode_search_str(out, is->search_str);
- buf_puts(out, " with ");
- buf_encode_search_str(out, is->replace_str);
- buf_puts(out, ": ");
-
- s->offset = is->found_end;
- s->b->mark = is->found_offset;
- s->region_style = QE_STYLE_SEARCH_MATCH;
- do_center_cursor_maybe(s);
- edit_display(s->qe_state);
- put_status(NULL, "%s", out->buf);
- dpy_flush(s->screen);
-}
-
-static void query_replace_key(void *opaque, int ch)
-{
- QueryReplaceState *is = opaque;
- EditState *s = is->s;
- QEmacsState *qs = &qe_state;
-
- switch (ch) {
- case 'Y':
- case 'y':
- case KEY_SPC:
- query_replace_replace(is);
- s->offset = is->found_offset;
- break;
- case '!':
- is->replace_all = 1;
- break;
- case 'N':
- case 'n':
- case KEY_DELETE:
- is->found_offset = is->found_end;
- break;
- case KEY_META('w'):
- case KEY_CTRL('w'):
- /* toggle word match */
- is->search_flags ^= SEARCH_FLAG_WORD;
- is->found_offset = is->last_offset;
- break;
- case KEY_META('b'):
- case KEY_CTRL('b'):
- /* cycle unihex, hex, normal search */
- if (is->search_flags & SEARCH_FLAG_UNIHEX)
- is->search_flags ^= SEARCH_FLAG_HEX | SEARCH_FLAG_UNIHEX;
- else
- if (is->search_flags & SEARCH_FLAG_HEX)
- is->search_flags ^= SEARCH_FLAG_HEX;
- else
- is->search_flags ^= SEARCH_FLAG_UNIHEX;
- is->found_offset = is->last_offset;
- break;
- case KEY_META('c'):
- case KEY_CTRL('c'):
- /* toggle case sensitivity */
- if (is->search_flags & (SEARCH_FLAG_IGNORECASE |
SEARCH_FLAG_SMARTCASE)) {
- is->search_flags &= ~SEARCH_FLAG_IGNORECASE;
- } else {
- is->search_flags |= SEARCH_FLAG_IGNORECASE;
- }
- is->search_flags &= ~SEARCH_FLAG_SMARTCASE;
- is->found_offset = is->last_offset;
- break;
- case KEY_CTRL('g'):
- /* abort */
- if (qs->emulation_flags) {
- /* restore point to original location */
- s->offset = is->start_offset;
- }
- query_replace_abort(is);
- return;
- case KEY_CTRL('l'):
- do_center_cursor(s);
- break;
- case '.':
- query_replace_replace(is);
- s->offset = is->found_offset;
- /* FALL THRU */
- default:
- query_replace_abort(is);
- return;
- }
- query_replace_display(is);
-}
-
-static void query_replace(EditState *s, const char *search_str,
- const char *replace_str, int all, int flags)
-{
- QueryReplaceState *is;
-
- if (s->b->flags & BF_READONLY)
- return;
-
- is = qe_mallocz(QueryReplaceState);
- if (!is)
- return;
- is->s = s;
- pstrcpy(is->search_str, sizeof(is->search_str), search_str);
- pstrcpy(is->replace_str, sizeof(is->replace_str), replace_str);
-
- if (s->hex_mode) {
- if (s->unihex_mode)
- flags = SEARCH_FLAG_UNIHEX;
- else
- flags = SEARCH_FLAG_HEX;
- }
- is->search_flags = flags;
- is->replace_all = all;
- is->start_offset = is->last_offset = s->offset;
- is->found_offset = is->found_end = s->offset;
-
- qe_grab_keys(query_replace_key, is);
- query_replace_display(is);
-}
-
-void do_query_replace(EditState *s, const char *search_str,
- const char *replace_str)
-{
- int flags = SEARCH_FLAG_SMARTCASE;
- query_replace(s, search_str, replace_str, 0, flags);
-}
-
-void do_replace_string(EditState *s, const char *search_str,
- const char *replace_str, int argval)
-{
- int flags = SEARCH_FLAG_SMARTCASE;
- if (argval != NO_ARG)
- flags |= SEARCH_FLAG_WORD;
- query_replace(s, search_str, replace_str, 1, flags);
-}
-
-void do_search_string(EditState *s, const char *search_str, int dir)
-{
- unsigned int search_u32[SEARCH_LENGTH];
- int search_u32_len;
- int found_offset, found_end;
- int flags = SEARCH_FLAG_SMARTCASE;
-
- if (s->hex_mode) {
- if (s->unihex_mode)
- flags |= SEARCH_FLAG_UNIHEX;
- else
- flags |= SEARCH_FLAG_HEX;
- }
- search_u32_len = search_to_u32(search_u32, countof(search_u32),
- search_str, flags);
- if (eb_search(s->b, s->offset, dir, flags, search_u32, search_u32_len,
- NULL, NULL, &found_offset, &found_end) > 0) {
- s->offset = (dir < 0) ? found_offset : found_end;
- do_center_cursor_maybe(s);
- } else {
- put_status(s, "Search failed: \"%s\"", search_str);
- }
-}
-
/*----------------*/
void do_doctor(EditState *s)
@@ -8087,7 +7316,7 @@
const char str_version[] = "QEmacs version " QE_VERSION;
const char str_credits[] = "Copyright (c) 2000-2003 Fabrice Bellard\n"
- "Copyright (c) 2000-2014 Charlie Gordon\n";
+ "Copyright (c) 2000-2015 Charlie Gordon\n";
static void show_version(void)
{
@@ -8131,7 +7360,7 @@
exit(1);
}
-int parse_command_line(int argc, char **argv)
+static int parse_command_line(int argc, char **argv)
{
int _optind;
Index: search.c
===================================================================
RCS file: search.c
diff -N search.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ search.c 17 Aug 2015 16:56:49 -0000 1.1
@@ -0,0 +1,794 @@
+/*
+ * QEmacs, tiny but powerful multimode editor
+ *
+ * Copyright (c) 2000-2002 Fabrice Bellard.
+ * Copyright (c) 2000-2015 Charlie Gordon.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "qe.h"
+#include "variables.h"
+
+/* Search stuff */
+
+#define SEARCH_FLAG_SMARTCASE 0x0001 /* case fold unless upper case present
*/
+#define SEARCH_FLAG_IGNORECASE 0x0002
+#define SEARCH_FLAG_WORD 0x0004
+#define SEARCH_FLAG_WRAPPED 0x0008
+#define SEARCH_FLAG_HEX 0x0010
+#define SEARCH_FLAG_UNIHEX 0x0020
+
+/* XXX: OPTIMIZE ! */
+static int eb_search(EditBuffer *b, int start_offset, int dir, int flags,
+ const unsigned int *buf, int len,
+ CSSAbortFunc *abort_func, void *abort_opaque,
+ int *found_offset, int *found_end)
+{
+ int total_size = b->total_size;
+ int c, c2, offset = start_offset, offset1, offset2, offset3, pos;
+
+ if (len == 0)
+ return 0;
+
+ *found_offset = -1;
+ *found_end = -1;
+
+ /* analyze buffer if smart case */
+ if (flags & SEARCH_FLAG_SMARTCASE) {
+ int upper_count = 0;
+ int lower_count = 0;
+ for (pos = 0; pos < len; pos++) {
+ lower_count += qe_islower(buf[pos]);
+ upper_count += qe_isupper(buf[pos]);
+ }
+ if (lower_count > 0 && upper_count == 0)
+ flags |= SEARCH_FLAG_IGNORECASE;
+ }
+
+ if (flags & SEARCH_FLAG_HEX) {
+ /* handle buffer as single bytes */
+ /* XXX: should handle ucs2 and ucs4 as words */
+ for (;; (void)(dir >= 0 && offset++)) {
+ if (dir < 0) {
+ if (offset == 0)
+ return 0;
+ offset--;
+ }
+ if (offset >= total_size)
+ return 0;
+
+ if ((offset & 0xfffff) == 0) {
+ /* check for search abort every megabyte */
+ if (abort_func && abort_func(abort_opaque))
+ return -1;
+ }
+
+ pos = 0;
+ for (offset2 = offset; offset2 < total_size;) {
+ /* CG: Should bufferize a bit ? */
+ c = eb_read_one_byte(b, offset2++);
+ c2 = buf[pos++];
+ if (c != c2)
+ break;
+ if (pos >= len) {
+ /* check end of word */
+ *found_offset = offset;
+ *found_end = offset2;
+ return 1;
+ }
+ }
+ }
+ }
+
+ for (offset1 = offset;;) {
+ if (dir < 0) {
+ if (offset == 0)
+ return 0;
+ eb_prevc(b, offset, &offset);
+ } else {
+ offset = offset1;
+ if (offset >= total_size)
+ return 0;
+ }
+ if ((offset & 0xfffff) == 0) {
+ /* check for search abort every megabyte */
+ if (abort_func && abort_func(abort_opaque))
+ return -1;
+ }
+
+ if (flags & SEARCH_FLAG_WORD) {
+ /* check for start of word */
+ c = eb_prevc(b, offset, &offset3);
+ if (qe_isword(c))
+ continue;
+ }
+
+ /* CG: XXX: Should use buffer specific accelerator */
+ /* Get first char separately to compute offset1 */
+ c = eb_nextc(b, offset, &offset1);
+
+ pos = 0;
+ for (offset2 = offset1;;) {
+ c2 = buf[pos++];
+ if (flags & SEARCH_FLAG_IGNORECASE) {
+ if (qe_toupper(c) != qe_toupper(c2))
+ break;
+ } else {
+ if (c != c2)
+ break;
+ }
+ if (pos >= len) {
+ if (flags & SEARCH_FLAG_WORD) {
+ /* check for end of word */
+ c = eb_nextc(b, offset2, &offset3);
+ if (qe_isword(c))
+ break;
+ }
+ if (dir > 0 || offset2 <= start_offset) {
+ *found_offset = offset;
+ *found_end = offset2;
+ return 1;
+ }
+ }
+ if (offset2 >= total_size)
+ break;
+ c = eb_nextc(b, offset2, &offset2);
+ }
+ }
+}
+
+/* should separate search string length and number of match positions */
+#define SEARCH_LENGTH 256
+#define FOUND_TAG 0x80000000
+#define FOUND_REV 0x40000000
+
+/* store last searched string */
+static unsigned int last_search_u32[SEARCH_LENGTH];
+static int last_search_u32_len = 0;
+
+static int search_abort_func(__unused__ void *opaque)
+{
+ return is_user_input_pending();
+}
+
+typedef struct ISearchState {
+ EditState *s;
+ int saved_mark;
+ int start_offset;
+ int start_dir;
+ int quoting;
+ int dir;
+ int pos;
+ int search_flags;
+ int found_offset, found_end;
+ unsigned int search_u32[SEARCH_LENGTH];
+} ISearchState;
+
+static void buf_encode_search_u32(buf_t *out, const unsigned int *str, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++) {
+ unsigned int v = str[i];
+ if (!(v & FOUND_TAG)) {
+ if (v < 32 || v == 127) {
+ buf_printf(out, "^%c", (v + '@') & 127);
+ } else {
+ buf_putc_utf8(out, v);
+ }
+ if (buf_avail(out) <= 0)
+ break;
+ }
+ }
+}
+
+static void buf_encode_search_str(buf_t *out, const char *str)
+{
+ while (*str) {
+ int c = utf8_decode(&str);
+ if (c < 32 || c == 127) {
+ buf_printf(out, "^%c", (c + '@') & 127);
+ } else {
+ buf_putc_utf8(out, c);
+ }
+ if (buf_avail(out) <= 0)
+ break;
+ }
+}
+
+static void isearch_display(ISearchState *is)
+{
+ EditState *s = is->s;
+ char ubuf[256];
+ buf_t outbuf, *out;
+ unsigned int buf[SEARCH_LENGTH];
+ int c, i, len, hex_nibble, max_nibble, h, hc;
+ unsigned int v;
+ int search_offset, flags, dir = is->start_dir;
+
+ /* prepare the search bytes */
+ len = 0;
+ search_offset = is->start_offset;
+ max_nibble = hex_nibble = hc = 0;
+ flags = is->search_flags;
+ if (flags & SEARCH_FLAG_UNIHEX)
+ max_nibble = 6;
+ if (flags & SEARCH_FLAG_HEX)
+ max_nibble = 2;
+
+ for (i = 0; i < is->pos; i++) {
+ v = is->search_u32[i];
+ if (v & FOUND_TAG) {
+ dir = (v & FOUND_REV) ? -1 : 1;
+ search_offset = v & ~(FOUND_TAG | FOUND_REV);
+ continue;
+ }
+ c = v;
+ if (len < countof(buf)) {
+ if (max_nibble) {
+ h = to_hex(c);
+ if (h >= 0) {
+ hc = (hc << 4) | h;
+ if (++hex_nibble == max_nibble) {
+ buf[len++] = hc;
+ hex_nibble = hc = 0;
+ }
+ } else {
+ if (c == ' ' && hex_nibble) {
+ buf[len++] = hc;
+ hex_nibble = hc = 0;
+ }
+ }
+ } else {
+ buf[len++] = c;
+ }
+ }
+ }
+ if (hex_nibble >= 2) {
+ buf[len++] = hc;
+ hex_nibble = hc = 0;
+ }
+
+ is->dir = dir;
+
+ if (len == 0) {
+ s->b->mark = is->saved_mark;
+ s->offset = is->start_offset;
+ s->region_style = 0;
+ is->found_offset = -1;
+ } else {
+ if (eb_search(s->b, search_offset, is->dir, flags,
+ buf, len, search_abort_func, NULL,
+ &is->found_offset, &is->found_end) > 0) {
+ s->region_style = QE_STYLE_SEARCH_MATCH;
+ if (is->dir > 0) {
+ s->b->mark = is->found_offset;
+ s->offset = is->found_end;
+ } else {
+ s->b->mark = is->found_end;
+ s->offset = is->found_offset;
+ }
+ }
+ }
+
+ /* display search string */
+ out = buf_init(&outbuf, ubuf, sizeof(ubuf));
+ if (is->found_offset < 0 && len > 0)
+ buf_puts(out, "Failing ");
+ else
+ if (is->search_flags & SEARCH_FLAG_WRAPPED) {
+ buf_puts(out, "Wrapped ");
+ is->search_flags &= ~SEARCH_FLAG_WRAPPED;
+ }
+ if (is->search_flags & SEARCH_FLAG_UNIHEX)
+ buf_puts(out, "Unihex ");
+ if (is->search_flags & SEARCH_FLAG_HEX)
+ buf_puts(out, "Hex ");
+ if (is->search_flags & SEARCH_FLAG_WORD)
+ buf_puts(out, "Word ");
+ if (is->search_flags & SEARCH_FLAG_IGNORECASE)
+ buf_puts(out, "Folding ");
+ else
+ if (!(is->search_flags & SEARCH_FLAG_SMARTCASE))
+ buf_puts(out, "Exact ");
+
+ buf_puts(out, "I-search");
+ if (is->dir < 0)
+ buf_puts(out, " backward");
+ buf_puts(out, ": ");
+ buf_encode_search_u32(out, is->search_u32, is->pos);
+ if (is->quoting)
+ buf_puts(out, "^Q-");
+
+ /* display text */
+ do_center_cursor_maybe(s);
+ edit_display(s->qe_state);
+ put_status(NULL, "%s", out->buf);
+ dpy_flush(s->screen);
+}
+
+static int isearch_grab(ISearchState *is, EditBuffer *b, int from, int to)
+{
+ int offset, c, last = is->pos;
+ if (b) {
+ if (to < 0 || to > b->total_size)
+ to = b->total_size;
+ for (offset = from; is->pos < SEARCH_LENGTH && offset < to;) {
+ c = eb_nextc(b, offset, &offset);
+ is->search_u32[is->pos++] = c;
+ }
+ }
+ return is->pos - last;
+}
+
+static void isearch_key(void *opaque, int ch)
+{
+ ISearchState *is = opaque;
+ EditState *s = is->s;
+ QEmacsState *qs = &qe_state;
+ int i, j, offset0, offset1, curdir = is->dir;
+ int emacs_behaviour = !qs->emulation_flags;
+
+ if (is->quoting) {
+ is->quoting = 0;
+ if (!KEY_IS_SPECIAL(ch))
+ goto addch;
+ }
+ /* XXX: all these should be isearch-mode bindings */
+ switch (ch) {
+ case KEY_DEL:
+ case KEY_BS:
+ if (is->pos > 0)
+ is->pos--;
+ break;
+ case KEY_CTRL('g'):
+ s->b->mark = is->saved_mark;
+ s->offset = is->start_offset;
+ s->region_style = 0;
+ put_status(s, "Quit");
+ the_end:
+ /* save current searched string */
+ if (is->pos > 0) {
+ j = 0;
+ for (i = 0; i < is->pos; i++) {
+ if (!(is->search_u32[i] & FOUND_TAG))
+ last_search_u32[j++] = is->search_u32[i];
+ }
+ last_search_u32_len = j;
+ }
+ qe_ungrab_keys();
+ qe_free(&is);
+ edit_display(s->qe_state);
+ dpy_flush(s->screen);
+ return;
+ case KEY_CTRL('s'): /* next match */
+ is->dir = 1;
+ goto addpos;
+ case KEY_CTRL('r'): /* previous match */
+ is->dir = -1;
+ addpos:
+ /* use last seached string if no input */
+ if (is->pos == 0 && is->dir == curdir) {
+ memcpy(is->search_u32, last_search_u32,
+ last_search_u32_len * sizeof(*is->search_u32));
+ is->pos = last_search_u32_len;
+ } else
+ if (is->pos < SEARCH_LENGTH) {
+ /* add the match position, if any */
+ unsigned long v = is->dir > 0 ? FOUND_TAG : FOUND_TAG | FOUND_REV;
+ if (is->found_offset < 0) {
+ is->search_flags |= SEARCH_FLAG_WRAPPED;
+ if (is->dir < 0)
+ v |= s->b->total_size;
+ } else {
+ v |= s->offset;
+ }
+ is->search_u32[is->pos++] = v;
+ }
+ break;
+ case KEY_CTRL('q'):
+ is->quoting = 1;
+ break;
+ case KEY_META('w'):
+ emacs_behaviour ^= 1;
+ /* fall thru */
+ case KEY_CTRL('w'):
+ if (emacs_behaviour) {
+ /* grab word at cursor */
+ offset0 = s->offset;
+ do_word_right(s, 1);
+ offset1 = s->offset;
+ s->offset = offset0;
+ isearch_grab(is, s->b, offset0, offset1);
+ } else {
+ /* toggle word match */
+ is->search_flags ^= SEARCH_FLAG_WORD;
+ }
+ break;
+ case KEY_META('y'):
+ emacs_behaviour ^= 1;
+ /* fall thru */
+ case KEY_CTRL('y'):
+ if (emacs_behaviour) {
+ /* grab line at cursor */
+ offset0 = s->offset;
+ if (eb_nextc(s->b, offset0, &offset1) == '\n')
+ offset0 = offset1;
+ do_eol(s);
+ offset1 = s->offset;
+ s->offset = offset0;
+ isearch_grab(is, s->b, offset0, offset1);
+ } else {
+ /* yank into search string */
+ isearch_grab(is, qs->yank_buffers[qs->yank_current], 0, -1);
+ }
+ break;
+ case KEY_META('b'):
+ case KEY_CTRL('b'):
+ /* cycle unihex, hex, normal search */
+ if (is->search_flags & SEARCH_FLAG_UNIHEX)
+ is->search_flags ^= SEARCH_FLAG_HEX | SEARCH_FLAG_UNIHEX;
+ else
+ if (is->search_flags & SEARCH_FLAG_HEX)
+ is->search_flags ^= SEARCH_FLAG_HEX;
+ else
+ is->search_flags ^= SEARCH_FLAG_UNIHEX;
+ break;
+ case KEY_META('c'):
+ case KEY_CTRL('c'):
+ /* toggle case sensitivity */
+ if (is->search_flags & (SEARCH_FLAG_IGNORECASE |
SEARCH_FLAG_SMARTCASE)) {
+ is->search_flags &= ~SEARCH_FLAG_IGNORECASE;
+ } else {
+ is->search_flags |= SEARCH_FLAG_IGNORECASE;
+ }
+ is->search_flags &= ~SEARCH_FLAG_SMARTCASE;
+ break;
+ case KEY_CTRL('l'):
+ do_center_cursor(s);
+ break;
+ default:
+ if ((KEY_IS_SPECIAL(ch) || KEY_IS_CONTROL(ch)) && ch != '\t') {
+ /* exit search mode */
+#if 0
+ // FIXME: behaviour from qemacs-0.3pre13
+ if (is->found_offset >= 0) {
+ s->b->mark = is->found_offset;
+ } else {
+ s->b->mark = is->start_offset;
+ }
+ put_status(s, "Marked");
+#endif
+ s->b->mark = is->start_offset;
+ s->region_style = 0;
+ put_status(s, "Mark saved where search started");
+ /* repost key */
+ if (ch != KEY_RET)
+ unget_key(ch);
+ goto the_end;
+ } else {
+ addch:
+ if (is->pos < SEARCH_LENGTH) {
+ is->search_u32[is->pos++] = ch;
+ }
+ }
+ break;
+ }
+ isearch_display(is);
+}
+
+/* XXX: handle busy */
+void do_isearch(EditState *s, int dir)
+{
+ ISearchState *is;
+ int flags = SEARCH_FLAG_SMARTCASE;
+
+ is = qe_mallocz(ISearchState);
+ if (!is)
+ return;
+ is->s = s;
+ is->saved_mark = s->b->mark;
+ is->start_offset = s->offset;
+ is->start_dir = is->dir = dir;
+ is->pos = 0;
+ if (s->hex_mode) {
+ if (s->unihex_mode)
+ flags |= SEARCH_FLAG_UNIHEX;
+ else
+ flags |= SEARCH_FLAG_HEX;
+ }
+ is->search_flags = flags;
+
+ qe_grab_keys(isearch_key, is);
+ isearch_display(is);
+}
+
+static int search_to_u32(unsigned int *buf, int size,
+ const char *str, int flags)
+{
+ if (flags & (SEARCH_FLAG_HEX | SEARCH_FLAG_UNIHEX)) {
+ /* CG: XXX: Should mix utf8 and hex syntax in hex modes */
+ const char *s;
+ int c, hex_nibble, max_nibble, h, hc, len;
+
+ max_nibble = (flags & SEARCH_FLAG_UNIHEX) ? 6 : 2;
+ s = str;
+ hex_nibble = hc = 0;
+ for (len = 0; len < size;) {
+ c = *s++;
+ if (c == '\0') {
+ if (hex_nibble >= 2) {
+ buf[len++] = hc;
+ hex_nibble = hc = 0;
+ }
+ break;
+ }
+ h = to_hex(c);
+ if (h >= 0) {
+ hc = (hc << 4) | h;
+ if (++hex_nibble == max_nibble) {
+ buf[len++] = hc;
+ hex_nibble = hc = 0;
+ }
+ } else {
+ if (c == ' ' && hex_nibble) {
+ buf[len++] = hc;
+ hex_nibble = hc = 0;
+ }
+ }
+ }
+ return len;
+ } else {
+ return utf8_to_unicode(buf, size, str);
+ }
+}
+
+typedef struct QueryReplaceState {
+ EditState *s;
+ int start_offset;
+ int search_flags;
+ int replace_all;
+ int nb_reps;
+ int search_u32_len, replace_u32_len;
+ int found_offset, found_end;
+ int last_offset;
+ char search_str[SEARCH_LENGTH]; /* may be in hex */
+ char replace_str[SEARCH_LENGTH]; /* may be in hex */
+ unsigned int search_u32[SEARCH_LENGTH]; /* code points */
+ unsigned int replace_u32[SEARCH_LENGTH]; /* code points */
+} QueryReplaceState;
+
+static void query_replace_abort(QueryReplaceState *is)
+{
+ EditState *s = is->s;
+
+ qe_ungrab_keys();
+ s->b->mark = is->start_offset;
+ s->region_style = 0;
+ put_status(NULL, "Replaced %d occurrences", is->nb_reps);
+ qe_free(&is);
+ edit_display(s->qe_state);
+ dpy_flush(s->screen);
+}
+
+static void query_replace_replace(QueryReplaceState *is)
+{
+ EditState *s = is->s;
+
+ /* XXX: handle smart case replacement */
+ is->nb_reps++;
+ eb_delete(s->b, is->found_offset, is->found_end - is->found_offset);
+ is->found_offset += eb_insert_u32_buf(s->b, is->found_offset,
+ is->replace_u32, is->replace_u32_len);
+}
+
+static void query_replace_display(QueryReplaceState *is)
+{
+ EditState *s = is->s;
+ char ubuf[256];
+ buf_t outbuf, *out;
+
+ is->last_offset = is->found_offset;
+ is->search_u32_len = search_to_u32(is->search_u32,
+ countof(is->search_u32),
+ is->search_str, is->search_flags);
+ is->replace_u32_len = search_to_u32(is->replace_u32,
+ countof(is->replace_u32),
+ is->replace_str, is->search_flags);
+
+ for (;;) {
+ if (eb_search(s->b, is->found_offset, 1, is->search_flags,
+ is->search_u32, is->search_u32_len,
+ NULL, NULL, &is->found_offset, &is->found_end) <= 0) {
+ query_replace_abort(is);
+ return;
+ }
+ if (is->replace_all) {
+ query_replace_replace(is);
+ continue;
+ }
+ break;
+ }
+ /* display prompt string */
+ out = buf_init(&outbuf, ubuf, sizeof(ubuf));
+ if (is->search_flags & SEARCH_FLAG_UNIHEX)
+ buf_puts(out, "Unihex ");
+ if (is->search_flags & SEARCH_FLAG_HEX)
+ buf_puts(out, "Hex ");
+ if (is->search_flags & SEARCH_FLAG_WORD)
+ buf_puts(out, "Word ");
+ if (is->search_flags & SEARCH_FLAG_IGNORECASE)
+ buf_puts(out, "Folding ");
+ else
+ if (!(is->search_flags & SEARCH_FLAG_SMARTCASE))
+ buf_puts(out, "Exact ");
+
+ buf_puts(out, "Query replace ");
+ buf_encode_search_str(out, is->search_str);
+ buf_puts(out, " with ");
+ buf_encode_search_str(out, is->replace_str);
+ buf_puts(out, ": ");
+
+ s->offset = is->found_end;
+ s->b->mark = is->found_offset;
+ s->region_style = QE_STYLE_SEARCH_MATCH;
+ do_center_cursor_maybe(s);
+ edit_display(s->qe_state);
+ put_status(NULL, "%s", out->buf);
+ dpy_flush(s->screen);
+}
+
+static void query_replace_key(void *opaque, int ch)
+{
+ QueryReplaceState *is = opaque;
+ EditState *s = is->s;
+ QEmacsState *qs = &qe_state;
+
+ switch (ch) {
+ case 'Y':
+ case 'y':
+ case KEY_SPC:
+ query_replace_replace(is);
+ s->offset = is->found_offset;
+ break;
+ case '!':
+ is->replace_all = 1;
+ break;
+ case 'N':
+ case 'n':
+ case KEY_DELETE:
+ is->found_offset = is->found_end;
+ break;
+ case KEY_META('w'):
+ case KEY_CTRL('w'):
+ /* toggle word match */
+ is->search_flags ^= SEARCH_FLAG_WORD;
+ is->found_offset = is->last_offset;
+ break;
+ case KEY_META('b'):
+ case KEY_CTRL('b'):
+ /* cycle unihex, hex, normal search */
+ if (is->search_flags & SEARCH_FLAG_UNIHEX)
+ is->search_flags ^= SEARCH_FLAG_HEX | SEARCH_FLAG_UNIHEX;
+ else
+ if (is->search_flags & SEARCH_FLAG_HEX)
+ is->search_flags ^= SEARCH_FLAG_HEX;
+ else
+ is->search_flags ^= SEARCH_FLAG_UNIHEX;
+ is->found_offset = is->last_offset;
+ break;
+ case KEY_META('c'):
+ case KEY_CTRL('c'):
+ /* toggle case sensitivity */
+ if (is->search_flags & (SEARCH_FLAG_IGNORECASE |
SEARCH_FLAG_SMARTCASE)) {
+ is->search_flags &= ~SEARCH_FLAG_IGNORECASE;
+ } else {
+ is->search_flags |= SEARCH_FLAG_IGNORECASE;
+ }
+ is->search_flags &= ~SEARCH_FLAG_SMARTCASE;
+ is->found_offset = is->last_offset;
+ break;
+ case KEY_CTRL('g'):
+ /* abort */
+ if (qs->emulation_flags) {
+ /* restore point to original location */
+ s->offset = is->start_offset;
+ }
+ query_replace_abort(is);
+ return;
+ case KEY_CTRL('l'):
+ do_center_cursor(s);
+ break;
+ case '.':
+ query_replace_replace(is);
+ s->offset = is->found_offset;
+ /* FALL THRU */
+ default:
+ query_replace_abort(is);
+ return;
+ }
+ query_replace_display(is);
+}
+
+static void query_replace(EditState *s, const char *search_str,
+ const char *replace_str, int all, int flags)
+{
+ QueryReplaceState *is;
+
+ if (s->b->flags & BF_READONLY)
+ return;
+
+ is = qe_mallocz(QueryReplaceState);
+ if (!is)
+ return;
+ is->s = s;
+ pstrcpy(is->search_str, sizeof(is->search_str), search_str);
+ pstrcpy(is->replace_str, sizeof(is->replace_str), replace_str);
+
+ if (s->hex_mode) {
+ if (s->unihex_mode)
+ flags = SEARCH_FLAG_UNIHEX;
+ else
+ flags = SEARCH_FLAG_HEX;
+ }
+ is->search_flags = flags;
+ is->replace_all = all;
+ is->start_offset = is->last_offset = s->offset;
+ is->found_offset = is->found_end = s->offset;
+
+ qe_grab_keys(query_replace_key, is);
+ query_replace_display(is);
+}
+
+void do_query_replace(EditState *s, const char *search_str,
+ const char *replace_str)
+{
+ int flags = SEARCH_FLAG_SMARTCASE;
+ query_replace(s, search_str, replace_str, 0, flags);
+}
+
+void do_replace_string(EditState *s, const char *search_str,
+ const char *replace_str, int argval)
+{
+ int flags = SEARCH_FLAG_SMARTCASE;
+ if (argval != NO_ARG)
+ flags |= SEARCH_FLAG_WORD;
+ query_replace(s, search_str, replace_str, 1, flags);
+}
+
+void do_search_string(EditState *s, const char *search_str, int dir)
+{
+ unsigned int search_u32[SEARCH_LENGTH];
+ int search_u32_len;
+ int found_offset, found_end;
+ int flags = SEARCH_FLAG_SMARTCASE;
+
+ if (s->hex_mode) {
+ if (s->unihex_mode)
+ flags |= SEARCH_FLAG_UNIHEX;
+ else
+ flags |= SEARCH_FLAG_HEX;
+ }
+ search_u32_len = search_to_u32(search_u32, countof(search_u32),
+ search_str, flags);
+ if (eb_search(s->b, s->offset, dir, flags, search_u32, search_u32_len,
+ NULL, NULL, &found_offset, &found_end) > 0) {
+ s->offset = (dir < 0) ? found_offset : found_end;
+ do_center_cursor_maybe(s);
+ } else {
+ put_status(s, "Search failed: \"%s\"", search_str);
+ }
+}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Qemacs-commit] qemacs Makefile qe.h qe.c search.c,
Charlie Gordon <=