[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemacs-commit] qemacs buffer.c qe.c qe.h qestyles.h
From: |
Charlie Gordon |
Subject: |
[Qemacs-commit] qemacs buffer.c qe.c qe.h qestyles.h |
Date: |
Sat, 15 Aug 2015 13:08:42 +0000 |
CVSROOT: /sources/qemacs
Module name: qemacs
Changes by: Charlie Gordon <chqrlie> 15/08/15 13:08:42
Modified files:
. : buffer.c qe.c qe.h qestyles.h
Log message:
searching: many improvements
- clean search and replace code
- fix point position upon matches in forward and backward directions
- prevent reverse search from find overlapping matches
- hilite current match
- add style search-match to hilite the current match in
incremental-search
defaults to cyan / magenta
- C-l centers the window
- C-q quotes next character in incremental search
- C-w grabs the word at point
- C-y grabs from point to next end of line
- A-b cycles unihex hex and normal search
- A-w toggles word matching
- A-y yanks last kill in search string
- add same control keys to query-replace command
- fix searching and replacing in hex and unihex modes
- wrap search after failure
- pass search data as u32 buffer
- add eb_insert_u32_buf(b, offset, buf, len) to insert unicode code
points
- add window.offset_end -> offset of first char beyond the window
- add qestate.emulation_flags to select between standard emacs
behaviour and
alternate behaviours in internal commands
- fix do_center_cursor() when point is before window start
- add do_center_cursor_maybe() to center window if point is not visible
- allow C-q to quote DEL key (ASCII 127)
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/qemacs/buffer.c?cvsroot=qemacs&r1=1.83&r2=1.84
http://cvs.savannah.gnu.org/viewcvs/qemacs/qe.c?cvsroot=qemacs&r1=1.195&r2=1.196
http://cvs.savannah.gnu.org/viewcvs/qemacs/qe.h?cvsroot=qemacs&r1=1.193&r2=1.194
http://cvs.savannah.gnu.org/viewcvs/qemacs/qestyles.h?cvsroot=qemacs&r1=1.9&r2=1.10
Patches:
Index: buffer.c
===================================================================
RCS file: /sources/qemacs/qemacs/buffer.c,v
retrieving revision 1.83
retrieving revision 1.84
diff -u -b -r1.83 -r1.84
--- buffer.c 8 Jun 2015 06:54:59 -0000 1.83
+++ buffer.c 15 Aug 2015 13:08:41 -0000 1.84
@@ -1825,15 +1825,15 @@
int eb_insert_spaces(EditBuffer *b, int offset, int n)
{
char buf1[1024];
- int size, size1;
+ int size, pos1;
- size = size1 = 0;
+ size = pos1 = 0;
while (n-- > 0) {
- int clen = eb_encode_uchar(b, buf1 + size1, ' ');
- size1 += clen;
- if (size1 > ssizeof(buf1) - MAX_CHAR_BYTES || n == 0) {
- size += eb_insert(b, offset + size, buf1, size1);
- size1 = 0;
+ int clen = eb_encode_uchar(b, buf1 + pos1, ' ');
+ pos1 += clen;
+ if (pos1 > ssizeof(buf1) - MAX_CHAR_BYTES || n == 0) {
+ size += eb_insert(b, offset + size, buf1, pos1);
+ pos1 = 0;
}
}
return size;
@@ -1864,6 +1864,26 @@
}
}
+/* Insert chars from u32 array according to buffer encoding */
+/* Return number of bytes inserted */
+int eb_insert_u32_buf(EditBuffer *b, int offset, const unsigned int *buf, int
len)
+{
+ char buf1[1024];
+ int pos, size, pos1;
+
+ pos = size = pos1 = 0;
+ while (pos < len) {
+ int c = buf[pos++];
+ int clen = eb_encode_uchar(b, buf1 + pos1, c);
+ pos1 += clen;
+ if (pos1 > ssizeof(buf) - MAX_CHAR_BYTES || pos >= len) {
+ size += eb_insert(b, offset + size, buf1, pos1);
+ pos1 = 0;
+ }
+ }
+ return size;
+}
+
int eb_insert_str(EditBuffer *b, int offset, const char *str)
{
return eb_insert_utf8_buf(b, offset, str, strlen(str));
Index: qe.c
===================================================================
RCS file: /sources/qemacs/qemacs/qe.c,v
retrieving revision 1.195
retrieving revision 1.196
diff -u -b -r1.195 -r1.196
--- qe.c 11 Aug 2015 22:15:38 -0000 1.195
+++ qe.c 15 Aug 2015 13:08:42 -0000 1.196
@@ -415,9 +415,11 @@
QEmacsState *qs = s->qe_state;
if (strequal(name, "epsilon")) {
+ qs->emulation_flags = 1;
qs->flag_split_window_change_focus = 1;
} else
if (strequal(name, "emacs") || strequal(name, "xemacs")) {
+ qs->emulation_flags = 0;
qs->flag_split_window_change_focus = 0;
} else
if (strequal(name, "vi") || strequal(name, "vim")) {
@@ -1144,6 +1146,12 @@
if (!s->mode->text_display)
return;
+ if (s->offset < s->offset_top) {
+ int offset_top = s->offset_top;
+ eb_prevc(s->b, offset_top, &offset_top);
+ s->offset_top = s->mode->text_backward_offset(s, offset_top);
+ }
+
get_cursor_pos(s, &cm);
if (cm.xc == NO_CURSOR)
return;
@@ -1152,6 +1160,15 @@
perform_scroll_up_down(s, -((s->height / 2) - cm.yc));
}
+/* center window if offset is not currently visible */
+static void do_center_cursor_maybe(EditState *s)
+{
+ if (s->offset < s->offset_top
+ || (s->offset_bottom >= 0 && s->offset >= s->offset_bottom)) {
+ do_center_cursor(s);
+ }
+}
+
/* called each time the cursor could be displayed */
typedef struct {
int yd;
@@ -1497,7 +1514,7 @@
return;
/* CG: why not insert special keys as well? */
- if (!KEY_SPECIAL(key) || (key >= 0 && key <= 31)) {
+ if (!KEY_IS_SPECIAL(key)) {
do_char(s, key, qa->argval);
edit_display(s->qe_state);
dpy_flush(&global_screen);
@@ -3196,8 +3213,12 @@
int offset = e->offset;
if ((offset1 >= offset && offset1 < mark) ||
- (offset1 >= mark && offset1 < offset))
+ (offset1 >= mark && offset1 < offset)) {
+ if (e->show_selection)
style |= QE_STYLE_SEL;
+ else
+ style = e->region_style;
+ }
}
/* special patch for selection in hex mode */
if (offset1 == offset2) {
@@ -3297,6 +3318,7 @@
offset = e->offset_top;
for (;;) {
offset = e->mode->text_display(e, s, offset);
+ e->offset_bottom = offset;
/* EOF reached ? */
if (offset < 0)
break;
@@ -3649,7 +3671,7 @@
/* colorize regions */
if (s->curline_style || s->region_style) {
/* CG: Should combine styles instead of replacing */
- if (s->region_style) {
+ if (!s->curline_style && s->region_style) {
int line, start, stop;
if (s->b->mark < s->offset) {
@@ -3732,7 +3754,7 @@
{
CursorContext m1, *m = &m1;
DisplayState ds1, *ds = &ds1;
- int x1, xc, yc, offset;
+ int x1, xc, yc, offset, bottom = -1;
/* if the cursor is before the top of the display zone, we must
resync backward */
@@ -3762,6 +3784,7 @@
s->y_disp = ds->y;
}
offset = s->mode->text_display(s, ds, offset);
+ s->offset_bottom = offset;
if (offset < 0 || ds->y >= s->height || m->xc != NO_CURSOR)
break;
}
@@ -3774,7 +3797,7 @@
ds->cursor_func = cursor_func;
ds->y = 0;
offset = s->mode->text_backward_offset(s, s->offset);
- s->mode->text_display(s, ds, offset);
+ bottom = s->mode->text_display(s, ds, offset);
if (m->xc == NO_CURSOR) {
/* XXX: should not happen */
put_error(NULL, "ERROR: cursor not found");
@@ -3786,9 +3809,10 @@
while (ds->y < s->height && offset > 0) {
eb_prevc(s->b, offset, &offset);
offset = s->mode->text_backward_offset(s, offset);
- s->mode->text_display(s, ds, offset);
+ bottom = s->mode->text_display(s, ds, offset);
}
s->offset_top = offset;
+ s->offset_bottom = bottom;
/* adjust y_disp so that the cursor is at the bottom of the
screen */
s->y_disp = s->height - ds->y;
@@ -4635,7 +4659,7 @@
unsigned int key_default = KEY_DEFAULT;
if (c->nb_keys == 1) {
- if (!KEY_SPECIAL(key)) {
+ if (!KEY_IS_SPECIAL(key) && !KEY_IS_CONTROL(key)) {
if (c->is_numeric_arg) {
if (qe_isdigit(key)) {
if (c->argval == NO_ARG)
@@ -6405,55 +6429,78 @@
/* Search stuff */
-#define SEARCH_FLAG_IGNORECASE 0x0001
-#define SEARCH_FLAG_SMARTCASE 0x0002 /* case sensitive if upper case present
*/
+#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 ! */
-int eb_search(EditBuffer *b, int offset, int dir, int flags,
- const char *buf, int size,
+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, offset1, offset2;
- char buf1[1024];
- const char *bufp, *bufend;
+ int c, c2, offset = start_offset, offset1, offset2, pos;
- if (size == 0 || size >= (int)sizeof(buf1))
+ if (len == 0)
return 0;
+ *found_offset = -1;
+ *found_end = -1;
+
+ 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 meg */
+ if (abort_func && abort_func(abort_opaque))
+ return 0;
+ }
+
+ pos = 0;
+ for (offset2 = offset; offset2 < total_size;) {
+ u8 data[1];
+
+ /* CG: Should bufferize a bit ? */
+ eb_read(b, offset2++, data, 1);
+ c = data[0];
+ c2 = buf[pos++];
+ if (c != c2)
+ break;
+ if (pos >= len) {
+ /* check end of word */
+ *found_offset = offset;
+ *found_end = offset2;
+ return 1;
+ }
+ }
+ }
+ }
+
/* analyze buffer if smart case */
if (flags & SEARCH_FLAG_SMARTCASE) {
int upper_count = 0;
int lower_count = 0;
- bufp = buf;
- bufend = buf + size;
- while (bufp < bufend) {
- c = utf8_decode(&bufp);
- lower_count += qe_islower(c);
- upper_count += qe_isupper(c);
+ 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;
}
- /* copy buffer */
- if (flags & SEARCH_FLAG_IGNORECASE) {
- bufp = buf;
- bufend = buf + size;
- size = 0;
- while (bufp < bufend) {
- c = utf8_decode(&bufp);
- size += utf8_encode(buf1 + size, qe_toupper(c));
- }
- } else {
- memcpy(buf1, buf, size);
- }
-
- *found_offset = -1;
- *found_end = -1;
-
for (;; (void)(dir >= 0 && eb_nextc(b, offset, &offset))) {
if (dir < 0) {
if (offset == 0)
@@ -6463,52 +6510,57 @@
if (offset >= total_size)
return 0;
- /* search abort */
- if ((offset & 0xfff) == 0) {
+ if ((offset & 0x1ffff) == 0) {
+ /* check for search abort every 128k */
if (abort_func && abort_func(abort_opaque))
return 0;
}
- /* search start of word */
if (flags & SEARCH_FLAG_WORD) {
+ /* check for start of word */
c = eb_prevc(b, offset, &offset1);
if (qe_isword(c))
continue;
}
- bufp = buf1;
- bufend = buf1 + size;
+ pos = 0;
offset2 = offset;
while (offset2 < total_size) {
- /* CG: Should bufferize a bit ? */
+ /* CG: XXX: Should use buffer specific accelerator */
c = eb_nextc(b, offset2, &offset2);
- if (flags & SEARCH_FLAG_IGNORECASE)
- c = qe_toupper(c);
- c2 = utf8_decode(&bufp);
+ c2 = buf[pos++];
+ if (flags & SEARCH_FLAG_IGNORECASE) {
+ if (qe_toupper(c) != qe_toupper(c2))
+ break;
+ } else {
if (c != c2)
break;
- if (bufp >= bufend) {
- /* check end of word */
+ }
+ if (pos >= len) {
if (flags & SEARCH_FLAG_WORD) {
+ /* check for end of word */
c = eb_nextc(b, offset2, &offset1);
if (qe_isword(c))
break;
}
+ if (dir > 0 || offset2 <= start_offset) {
*found_offset = offset;
*found_end = offset2;
return 1;
}
}
}
+ }
}
/* 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_string[SEARCH_LENGTH];
-static int last_search_string_len = 0;
+static unsigned int last_search_u32[SEARCH_LENGTH];
+static int last_search_u32_len = 0;
int search_abort_func(__unused__ void *opaque)
{
@@ -6517,65 +6569,121 @@
typedef struct ISearchState {
EditState *s;
+ int saved_mark;
int start_offset;
+ int start_dir;
+ int quoting;
int dir;
int pos;
- int stack_ptr;
int search_flags;
int found_offset, found_end;
- unsigned int search_string[SEARCH_LENGTH];
+ 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;
- char buf[2*SEARCH_LENGTH], *q; /* XXX: incorrect size */
- int i, len, hex_nibble, h;
+ unsigned int buf[SEARCH_LENGTH];
+ int c, i, len, hex_nibble, max_nibble, h, hc;
unsigned int v;
- int search_offset;
- int flags;
+ int search_offset, flags, dir = is->start_dir;
/* prepare the search bytes */
- q = buf;
+ len = 0;
search_offset = is->start_offset;
- hex_nibble = 0;
+ 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_string[i];
- if (!(v & FOUND_TAG)) {
- if ((q - buf) < ((int)sizeof(buf) - 10)) {
- if (s->hex_mode) {
- h = to_hex(v);
+ 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) {
- if (hex_nibble == 0)
- *q = h << 4;
- else
- *q++ |= h;
- hex_nibble ^= 1;
+ hc = (hc << 4) | h;
+ if (++hex_nibble == max_nibble) {
+ buf[len++] = hc;
+ hex_nibble = hc = 0;
}
- /* CG: should handle unihex mode */
} else {
- q += utf8_encode(q, v);
+ if (c == ' ' && hex_nibble) {
+ buf[len++] = hc;
+ hex_nibble = hc = 0;
}
}
} else {
- /* CG: XXX: offset cannot be adjusted this way */
- search_offset = (v & ~FOUND_TAG) + is->dir;
+ buf[len++] = c;
+ }
+ }
}
+ if (hex_nibble >= 2) {
+ buf[len++] = hc;
+ hex_nibble = hc = 0;
}
- len = q - buf;
+
+ 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 {
- flags = is->search_flags;
- if (s->hex_mode)
- flags = 0;
if (eb_search(s->b, search_offset, is->dir, flags,
buf, len, search_abort_func, NULL,
&is->found_offset, &is->found_end)) {
+ 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;
+ }
}
}
@@ -6583,39 +6691,35 @@
out = buf_init(&outbuf, ubuf, sizeof(ubuf));
if (is->found_offset < 0 && len > 0)
buf_puts(out, "Failing ");
- if (s->hex_mode) {
- buf_puts(out, "hex ");
- } else {
+ 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 ");
+ buf_puts(out, "Word ");
if (is->search_flags & SEARCH_FLAG_IGNORECASE)
- buf_puts(out, "case-insensitive ");
- else if (!(is->search_flags & SEARCH_FLAG_SMARTCASE))
- buf_puts(out, "case-sensitive ");
- }
+ 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, ": ");
- for (i = 0; i < is->pos; i++) {
- v = is->search_string[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;
- }
- }
+ buf_encode_search_u32(out, is->search_u32, is->pos);
+ if (is->quoting)
+ buf_puts(out, "^Q-");
/* display text */
- do_center_cursor(s);
+ do_center_cursor_maybe(s);
edit_display(s->qe_state);
-
put_status(NULL, "%s", out->buf);
-
dpy_flush(s->screen);
}
@@ -6623,10 +6727,11 @@
{
int offset, c, last = is->pos;
if (b) {
- if (to < 0 || to > b->total_size) to = b->total_size;
+ 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_string[is->pos++] = c;
+ is->search_u32[is->pos++] = c;
}
}
return is->pos - last;
@@ -6637,26 +6742,35 @@
ISearchState *is = opaque;
EditState *s = is->s;
QEmacsState *qs = &qe_state;
- int i, j, offset0, offset1;
+ 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: /* Should test actual binding of KEY_BS */
+ 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_string[i] & FOUND_TAG))
- last_search_string[j++] = is->search_string[i];
+ if (!(is->search_u32[i] & FOUND_TAG))
+ last_search_u32[j++] = is->search_u32[i];
}
- last_search_string_len = j;
+ last_search_u32_len = j;
}
qe_ungrab_keys();
qe_free(&is);
@@ -6670,52 +6784,86 @@
is->dir = -1;
addpos:
/* use last seached string if no input */
- if (is->pos == 0) {
- memcpy(is->search_string, last_search_string,
- last_search_string_len * sizeof(unsigned int));
- is->pos = last_search_string_len;
- } else {
+ 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 */
- if (is->pos < SEARCH_LENGTH && is->found_offset >= 0)
- is->search_string[is->pos++] = FOUND_TAG | is->found_offset;
+ 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;
-#if 0
case KEY_CTRL('q'):
- ch = get_key(s->screen);
- goto addch;
- case KEY_CTRL('w'): /* emacs: get word */
- case KEY_CTRL('y'): /* emacs: get line */
+ is->quoting = 1;
break;
-#endif
- case KEY_CTRL('d'): /* get word */
+ 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 = offset1;
+ s->offset = offset0;
isearch_grab(is, s->b, offset0, offset1);
+ } else {
+ /* toggle word match */
+ is->search_flags ^= SEARCH_FLAG_WORD;
+ }
break;
- case KEY_CTRL('l'): /* get line */
+ 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 = offset1;
+ s->offset = offset0;
isearch_grab(is, s->b, offset0, offset1);
- break;
- case KEY_CTRL('y'): /* yank into search string */
+ } else {
+ /* yank into search string */
isearch_grab(is, qs->yank_buffers[qs->yank_current], 0, -1);
+ }
break;
- case KEY_CTRL('w'): /* toggle word match */
- is->search_flags ^= SEARCH_FLAG_WORD;
+ 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_CTRL('c'): /* toggle case sensitivity */
- is->search_flags ^= SEARCH_FLAG_IGNORECASE;
- is->search_flags &= ~SEARCH_FLAG_SMARTCASE;
+ 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;
+ }
+ break;
+ case KEY_CTRL('l'):
+ do_center_cursor(s);
break;
default:
- if (KEY_SPECIAL(ch) && ch != '\t') {
+ if ((KEY_IS_SPECIAL(ch) || KEY_IS_CONTROL(ch)) && ch != '\t') {
/* exit search mode */
#if 0
// FIXME: behaviour from qemacs-0.3pre13
@@ -6727,15 +6875,16 @@
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:
+ addch:
if (is->pos < SEARCH_LENGTH) {
- is->search_string[is->pos++] = ch;
+ is->search_u32[is->pos++] = ch;
}
}
break;
@@ -6747,68 +6896,81 @@
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->dir = dir;
+ is->start_dir = is->dir = dir;
is->pos = 0;
- is->stack_ptr = 0;
- is->search_flags = SEARCH_FLAG_SMARTCASE;
+ 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 to_bytes(EditState *s1, char *dst, int dst_size, const char *str)
+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, len, hex_nibble, h;
- char *d;
+ int c, hex_nibble, max_nibble, h, hc, len;
- d = dst;
- if (s1->hex_mode) {
+ max_nibble = (flags & SEARCH_FLAG_UNIHEX) ? 6 : 2;
s = str;
- h = 0;
- hex_nibble = 0;
- for (;;) {
+ hex_nibble = hc = 0;
+ for (len = 0; len < size;) {
c = *s++;
- if (c == '\0')
- break;
- c = to_hex(c);
- if (c >= 0) {
- h = (h << 4) | c;
- if (hex_nibble) {
- if (d < dst + dst_size)
- *d++ = h;
- h = 0;
+ if (c == '\0') {
+ if (hex_nibble >= 2) {
+ buf[len++] = hc;
+ hex_nibble = hc = 0;
}
- hex_nibble ^= 1;
+ break;
}
+ h = to_hex(c);
+ if (h >= 0) {
+ hc = (hc << 4) | h;
+ if (++hex_nibble == max_nibble) {
+ buf[len++] = hc;
+ hex_nibble = hc = 0;
}
- return d - dst;
} else {
- /* dest buffer has utf8 contents */
- len = strlen(str);
- if (len > dst_size)
- len = dst_size;
- memcpy(dst, str, len);
+ 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 nb_reps;
- int search_bytes_len, replace_bytes_len, found_offset, found_end;
+ int start_offset;
+ int search_flags;
int replace_all;
- int flags;
+ 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 */
- char search_bytes[SEARCH_LENGTH]; /* utf8 bytes */
- char replace_bytes[SEARCH_LENGTH]; /* utf8 bytes */
+ unsigned int search_u32[SEARCH_LENGTH]; /* code points */
+ unsigned int replace_u32[SEARCH_LENGTH]; /* code points */
} QueryReplaceState;
static void query_replace_abort(QueryReplaceState *is)
@@ -6816,6 +6978,8 @@
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);
@@ -6826,49 +6990,81 @@
{
EditState *s = is->s;
- eb_delete(s->b, is->found_offset, is->found_end - is->found_offset);
- is->found_offset += eb_insert_utf8_buf(s->b, is->found_offset,
- is->replace_bytes,
- is->replace_bytes_len);
+ /* 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);
- redo:
- if (!eb_search(s->b, is->found_offset, 1, is->flags,
- is->search_bytes, is->search_bytes_len,
+ 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)) {
query_replace_abort(is);
return;
}
-
if (is->replace_all) {
query_replace_replace(is);
- goto redo;
+ 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 ");
- /* display text */
- s->offset = is->found_offset;
- do_center_cursor(s);
- edit_display(s->qe_state);
+ 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, ": ");
- put_status(NULL, "Query replace %s with %s: ",
- is->search_str, is->replace_str);
- dpy_flush(&global_screen);
+ 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;
@@ -6876,9 +7072,51 @@
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);
@@ -6887,8 +7125,7 @@
query_replace_display(is);
}
-static void query_replace(EditState *s,
- const char *search_str,
+static void query_replace(EditState *s, const char *search_str,
const char *replace_str, int all, int flags)
{
QueryReplaceState *is;
@@ -6903,14 +7140,16 @@
pstrcpy(is->search_str, sizeof(is->search_str), search_str);
pstrcpy(is->replace_str, sizeof(is->replace_str), replace_str);
- is->search_bytes_len = to_bytes(s, is->search_bytes,
sizeof(is->search_bytes),
- search_str);
- is->replace_bytes_len = to_bytes(s, is->replace_bytes,
sizeof(is->replace_bytes),
- replace_str);
- is->nb_reps = 0;
+ 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;
- is->flags = flags;
qe_grab_keys(query_replace_key, is);
query_replace_display(is);
@@ -6919,29 +7158,38 @@
void do_query_replace(EditState *s, const char *search_str,
const char *replace_str)
{
- query_replace(s, search_str, replace_str, 0, 0);
+ 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)
{
- query_replace(s, search_str, replace_str, 1,
- argval == NO_ARG ? 0 : SEARCH_FLAG_WORD);
+ 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)
{
- char search_bytes[SEARCH_LENGTH];
- int search_bytes_len;
+ unsigned int search_u32[SEARCH_LENGTH];
+ int search_u32_len;
int found_offset, found_end;
+ int flags = 0;
- search_bytes_len = to_bytes(s, search_bytes, sizeof(search_bytes),
- search_str);
-
- if (eb_search(s->b, s->offset, dir, 0, search_bytes, search_bytes_len,
+ 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)) {
s->offset = (dir < 0) ? found_offset : found_end;
- do_center_cursor(s);
+ do_center_cursor_maybe(s);
}
}
Index: qe.h
===================================================================
RCS file: /sources/qemacs/qemacs/qe.h,v
retrieving revision 1.193
retrieving revision 1.194
diff -u -b -r1.193 -r1.194
--- qe.h 13 Aug 2015 23:26:59 -0000 1.193
+++ qe.h 15 Aug 2015 13:08:42 -0000 1.194
@@ -658,7 +658,8 @@
#define KEY_CTRLXRET(c) ((c) | 0xe300)
#define KEY_CTRLH(c) ((c) | 0xe500)
#define KEY_CTRLC(c) ((c) | 0xe600)
-#define KEY_SPECIAL(c) (((c) >= 0xe000 && (c) < 0xf000) || ((c) >= 0 && (c) <
32) || (c) == 127)
+#define KEY_IS_SPECIAL(c) ((c) >= 0xe000 && (c) < 0xf000)
+#define KEY_IS_CONTROL(c) (((c) >= 0 && (c) < 32) || (c) == 127)
#define KEY_NONE 0xffff
#define KEY_DEFAULT 0xe401 /* to handle all non special keys */
@@ -1015,6 +1016,7 @@
int eb_insert_uchar(EditBuffer *b, int offset, int c);
int eb_insert_spaces(EditBuffer *b, int offset, int n);
int eb_insert_utf8_buf(EditBuffer *b, int offset, const char *buf, int len);
+int eb_insert_u32_buf(EditBuffer *b, int offset, const unsigned int *buf, int
len);
int eb_insert_str(EditBuffer *b, int offset, const char *str);
int eb_match_uchar(EditBuffer *b, int offset, int c, int *offsetp);
int eb_match_str(EditBuffer *b, int offset, const char *str, int *offsetp);
@@ -1125,7 +1127,9 @@
struct EditState {
int offset; /* offset of the cursor */
/* text display state */
- int offset_top;
+ int offset_top; /* offset of first character displayed in window */
+ int offset_bottom; /* offset of first character beyond window or -1
+ * if end of file displayed */
int y_disp; /* virtual position of the displayed text */
int x_disp[2]; /* position for LTR and RTL text resp. */
int minibuf; /* true if single line editing */
@@ -1397,8 +1401,6 @@
int show_unicode;
/* commands */
- int flag_split_window_change_focus;
- int backspace_is_control_h;
/* XXX: move these to ec */
CmdFunc last_cmd_func; /* last executed command function call */
CmdFunc this_cmd_func; /* current executing command */
@@ -1433,6 +1435,9 @@
int default_tab_width; /* 8 */
int default_fill_column; /* 70 */
EOLType default_eol_type; /* EOL_UNIX */
+ int flag_split_window_change_focus;
+ int emulation_flags;
+ int backspace_is_control_h;
int backup_inhibited; /* prevent qemacs from backing up files */
int fuzzy_search; /* use fuzzy search for completion matcher */
};
@@ -1940,7 +1945,7 @@
void do_set_visited_file_name(EditState *s, const char *filename,
const char *renamefile);
int eb_search(EditBuffer *b, int offset, int dir, int flags,
- const char *buf, int size,
+ const unsigned int *buf, int size,
CSSAbortFunc *abort_func, void *abort_opaque,
int *found_start, int *found_end);
int search_abort_func(void *opaque);
Index: qestyles.h
===================================================================
RCS file: /sources/qemacs/qemacs/qestyles.h,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -b -r1.9 -r1.10
--- qestyles.h 30 May 2014 19:56:01 -0000 1.9
+++ qestyles.h 15 Aug 2015 13:08:42 -0000 1.10
@@ -73,6 +73,10 @@
COLOR_TRANSPARENT, QERGB(0x80, 0xf0, 0xf0),
0, 0)
+ STYLE_DEF(QE_STYLE_SEARCH_MATCH, "search-match",
+ QERGB(0xe0, 0xe0, 0xe0), QERGB(0xf0, 0x00, 0xf0),
+ 0, 0)
+
/* HTML coloring styles */
STYLE_DEF(QE_STYLE_HTML_COMMENT, "html-comment",
QERGB(0xf8, 0x44, 0x00), COLOR_TRANSPARENT,
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Qemacs-commit] qemacs buffer.c qe.c qe.h qestyles.h,
Charlie Gordon <=