Simplify and improve qe_check_buffer_file
* pass `QEmacsState` to key grab functions * clear `grab_key_opaque` when freeing windows, buffers, mode_data * add checks on window and buffer pointers in key grab functions * this should fix a crash bug when deleting unsynched buffers from bufed * fix `reload_buffer` to update buffer `file_size` and `mtime` fields * check buffer file before invoking commands that modify the buffer * check buffer file after command that changes the current window or the current window's buffer
This commit is contained in:
parent
eda70b4576
commit
6fb16e1cc2
8 changed files with 88 additions and 71 deletions
3
TODO.md
3
TODO.md
|
|
@ -11,8 +11,6 @@ This is the TODO list for qemacs
|
|||
* fix warning: `int (*eb_printf_fun)(EditBuffer *b, const char *fmt, ...) = (void*)eb_printf;`
|
||||
* fix crash bug on `C-X C-B C-X C-F xxx RET`
|
||||
* fix cursor positioning beyond end of screen
|
||||
* crash bug on reloading file contents in `qe_check_buffer_file()`
|
||||
* fix file change detection on buffer change (`C-x b`)
|
||||
|
||||
# Core - Buffers - Files
|
||||
|
||||
|
|
@ -64,6 +62,7 @@ This is the TODO list for qemacs
|
|||
|
||||
## Files
|
||||
|
||||
* show popup window with explanation and diff in `qe_check_buffer_file()`
|
||||
* fix corner cases in `qe_check_buffer_file()`
|
||||
* minimize edit list in `qe_check_buffer_file()` when new version is loaded
|
||||
* remanent annotations on files and buffers
|
||||
|
|
|
|||
17
buffer.c
17
buffer.c
|
|
@ -134,9 +134,6 @@ int eb_write(EditBuffer *b, int offset, const void *buf, int size)
|
|||
if (b->flags & BF_READONLY)
|
||||
return 0;
|
||||
|
||||
if (qe_check_buffer_file(b, CBF_MODIFY) == CBF_PROMPT)
|
||||
return 0;
|
||||
|
||||
/* We carefully clip the request, avoiding integer overflow */
|
||||
if (offset < 0 || size <= 0 || offset > b->total_size)
|
||||
return 0;
|
||||
|
|
@ -320,9 +317,6 @@ int eb_insert_buffer(EditBuffer *dest, int dest_offset,
|
|||
if (dest->flags & BF_READONLY)
|
||||
return 0;
|
||||
|
||||
if (qe_check_buffer_file(dest, CBF_MODIFY) == CBF_PROMPT)
|
||||
return 0;
|
||||
|
||||
/* Assert parameter consistency */
|
||||
if (dest_offset < 0 || src_offset < 0 || src_offset >= src->total_size)
|
||||
return 0;
|
||||
|
|
@ -461,9 +455,6 @@ int eb_insert(EditBuffer *b, int offset, const void *buf, int size)
|
|||
if (b->flags & BF_READONLY)
|
||||
return 0;
|
||||
|
||||
if (qe_check_buffer_file(b, CBF_MODIFY) == CBF_PROMPT)
|
||||
return 0;
|
||||
|
||||
/* sanity checks */
|
||||
if (offset > b->total_size)
|
||||
offset = b->total_size;
|
||||
|
|
@ -488,9 +479,6 @@ int eb_delete(EditBuffer *b, int offset, int size)
|
|||
if (b->flags & BF_READONLY)
|
||||
return 0;
|
||||
|
||||
if (qe_check_buffer_file(b, CBF_MODIFY) == CBF_PROMPT)
|
||||
return 0;
|
||||
|
||||
if (offset < 0 || offset >= b->total_size || size <= 0)
|
||||
return 0;
|
||||
|
||||
|
|
@ -816,6 +804,7 @@ void eb_free(EditBuffer **bp)
|
|||
EditBuffer **pb;
|
||||
EditBuffer *b1;
|
||||
|
||||
// XXX should use qe_free_mode_data()
|
||||
/* free b->mode_data_list by calling destructors */
|
||||
while (b->mode_data_list) {
|
||||
QEModeData *md = b->mode_data_list;
|
||||
|
|
@ -823,6 +812,8 @@ void eb_free(EditBuffer **bp)
|
|||
md->next = NULL;
|
||||
if (md->mode && md->mode->mode_free)
|
||||
md->mode->mode_free(b, md);
|
||||
if (qs->key_ctx.grab_key_opaque == md)
|
||||
qs->key_ctx.grab_key_opaque = NULL;
|
||||
qe_free(&md);
|
||||
}
|
||||
|
||||
|
|
@ -870,6 +861,8 @@ void eb_free(EditBuffer **bp)
|
|||
eb_free_style_buffer(b);
|
||||
|
||||
qe_free(&b->saved_data);
|
||||
if (qs->key_ctx.grab_key_opaque == b)
|
||||
qs->key_ctx.grab_key_opaque = NULL;
|
||||
// XXX: cannot use qe_free(bp) because *bp may have been set to NULL
|
||||
// already, eg: eb_free_log_buffer() and eb_free_style_buffer()
|
||||
qe_free(&b);
|
||||
|
|
|
|||
|
|
@ -309,7 +309,6 @@ static void bufed_select(EditState *s, int temp)
|
|||
do_delete_window(s, 1);
|
||||
if (e) {
|
||||
qs->active_window = e;
|
||||
qe_check_buffer_file(e->b, CBF_CHECK);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -1458,7 +1458,6 @@ static void dired_select(EditState *s, int mode)
|
|||
if (e) {
|
||||
#if 1
|
||||
s->qs->active_window = e;
|
||||
qe_check_buffer_file(e->b, CBF_CHECK);
|
||||
if (mode == 1) {
|
||||
/* XXX: should keep BF_PREVIEW flag and set pager-mode */
|
||||
e->b->flags &= ~BF_PREVIEW;
|
||||
|
|
@ -1544,7 +1543,6 @@ static void dired_parent(EditState *s, int collapse)
|
|||
EditState *e = find_window(s, KEY_LEFT, NULL);
|
||||
if (e && (e->flags & WF_FILELIST)) {
|
||||
s->qs->active_window = e;
|
||||
qe_check_buffer_file(e->b, CBF_CHECK);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1368,7 +1368,7 @@ static void shell_display_hook(EditState *e)
|
|||
}
|
||||
}
|
||||
|
||||
static void shell_key(void *opaque, int key)
|
||||
static void shell_key(QEmacsState *qs, void *opaque, int key)
|
||||
{
|
||||
ShellState *s = opaque;
|
||||
char buf[10];
|
||||
|
|
@ -1379,8 +1379,8 @@ static void shell_key(void *opaque, int key)
|
|||
return;
|
||||
|
||||
if (key == KEY_CTRL('o') && s->last_key_grabbed == KEY_CTRL(' ')) {
|
||||
qe_ungrab_keys(s->base.qs);
|
||||
qe_unget_key(s->base.qs, key);
|
||||
qe_ungrab_keys(qs);
|
||||
qe_unget_key(qs, key);
|
||||
s->last_key_grabbed = key;
|
||||
return;
|
||||
}
|
||||
|
|
@ -2878,7 +2878,6 @@ static EditBuffer *try_show_buffer(EditState **sp, const char *bufname)
|
|||
e = eb_find_window(b, NULL);
|
||||
if (e) {
|
||||
qs->active_window = *sp = e;
|
||||
qe_check_buffer_file(e->b, CBF_CHECK);
|
||||
} else {
|
||||
switch_to_buffer(s, b);
|
||||
}
|
||||
|
|
|
|||
92
qe.c
92
qe.c
|
|
@ -1783,7 +1783,6 @@ void text_mouse_goto(EditState *s, int x, int y, QEEvent *ev)
|
|||
if (!(curw && (curw->flags & (WF_POPUP | WF_MINIBUF)))
|
||||
&& !qs->key_ctx.grab_key_cb) {
|
||||
qs->active_window = s;
|
||||
qe_check_buffer_file(s->b, CBF_CHECK);
|
||||
}
|
||||
if (s->mouse_force_highlight)
|
||||
s->force_highlight = 1;
|
||||
|
|
@ -2021,14 +2020,13 @@ struct QuoteKeyArgument {
|
|||
};
|
||||
|
||||
/* XXX: may be better to move it into qe_key_process() */
|
||||
static void quote_key(void *opaque, int key)
|
||||
static void quote_key(QEmacsState *qs, void *opaque, int key)
|
||||
{
|
||||
// XXX: emacs supports octal input followed by RET
|
||||
// and f1 for context sensitive help
|
||||
// qemacs supports special keys and inserts the keyboard sequence
|
||||
struct QuoteKeyArgument *qa = opaque;
|
||||
EditState *s = qa->s;
|
||||
QEmacsState *qs = s->qs;
|
||||
EditState *s = qe_check_window(qs, &qa->s);
|
||||
int repeat = qa->argval;
|
||||
|
||||
put_status(s, ""); /* erase "Quote: " message */
|
||||
|
|
@ -2656,7 +2654,7 @@ static int reload_buffer(EditState *s, EditBuffer *b, int reload)
|
|||
}
|
||||
return -1;
|
||||
} else {
|
||||
if (stat(b->filename, &st) < 0) {
|
||||
if (!stat(b->filename, &st)) {
|
||||
b->file_mtime = st.st_mtime;
|
||||
b->file_size = st.st_size;
|
||||
}
|
||||
|
|
@ -2783,6 +2781,8 @@ int qe_free_mode_data(QEModeData *md)
|
|||
}
|
||||
if (rc == 0) {
|
||||
/* mode data was found, OK to free */
|
||||
if (md->qs->key_ctx.grab_key_opaque == md)
|
||||
md->qs->key_ctx.grab_key_opaque = NULL;
|
||||
qe_free(&md);
|
||||
}
|
||||
return rc;
|
||||
|
|
@ -5644,6 +5644,9 @@ void exec_command(EditState *s, const CmdDef *d, int argval, int key)
|
|||
put_error(s, "Buffer is read only");
|
||||
return;
|
||||
}
|
||||
if (qe_check_buffer_file(s->b, CBF_MODIFY) == CBF_PROMPT) {
|
||||
return;
|
||||
}
|
||||
} else
|
||||
if (*argdesc == '#') {
|
||||
argdesc++;
|
||||
|
|
@ -6626,7 +6629,7 @@ void do_prefix_argument(EditState *s, int key) {
|
|||
/*
|
||||
* All typed keys are sent to the callback. Previous grab is aborted
|
||||
*/
|
||||
void qe_grab_keys(QEmacsState *qs, void (*cb)(void *opaque, int key), void *opaque)
|
||||
void qe_grab_keys(QEmacsState *qs, void (*cb)(QEmacsState *qs, void *opaque, int key), void *opaque)
|
||||
{
|
||||
QEKeyContext *c = &qs->key_ctx;
|
||||
|
||||
|
|
@ -6722,7 +6725,7 @@ static void qe_key_process(QEmacsState *qs, int key)
|
|||
// XXX: shound test for help-popup
|
||||
if (c->grab_key_cb) {
|
||||
/* grabber should return codes for quit / fall thru / ungrab */
|
||||
c->grab_key_cb(c->grab_key_opaque, key);
|
||||
c->grab_key_cb(qs, c->grab_key_opaque, key);
|
||||
/* allow key_grabber to quit and unget last key */
|
||||
if (c->grab_key_cb || qs->ungot_key == -1)
|
||||
return;
|
||||
|
|
@ -6835,6 +6838,8 @@ static void qe_key_process(QEmacsState *qs, int key)
|
|||
} else {
|
||||
int argval = c->argval;
|
||||
int multi_cursor_active = s->multi_cursor_active;
|
||||
EditBuffer *this_buffer = s->b;
|
||||
|
||||
if (c->has_arg & HAS_ARG_NEGATIVE)
|
||||
argval = -argval;
|
||||
else
|
||||
|
|
@ -6853,12 +6858,18 @@ static void qe_key_process(QEmacsState *qs, int key)
|
|||
qs->last_key = key;
|
||||
}
|
||||
exec_command(s, d, argval, key);
|
||||
if (multi_cursor_active && qe_check_window(qs, &s)) {
|
||||
int i;
|
||||
if (s != qs->active_window) {
|
||||
/* end multi-cursor session upto window change */
|
||||
if (s != qs->active_window || s->b != this_buffer) {
|
||||
if (qe_check_window(qs, &s)) {
|
||||
/* end multi-cursor session upto window or buffer change */
|
||||
s->multi_cursor_active = 0;
|
||||
}
|
||||
if (!qs->key_ctx.grab_key_cb && qs->active_window) {
|
||||
qe_check_buffer_file(qs->active_window->b, CBF_CHECK);
|
||||
}
|
||||
} else
|
||||
if (multi_cursor_active) {
|
||||
// dispatch the command to all cursors if multi_cursor was already active
|
||||
int i;
|
||||
s->multi_cursor[0].offset = s->offset;
|
||||
for (i = 1; s->multi_cursor_active && i < s->multi_cursor_len; i++) {
|
||||
swap_int(&s->b->mark, &s->multi_cursor[i].mark);
|
||||
|
|
@ -7206,8 +7217,6 @@ static void edit_detach(EditState *s)
|
|||
/* if window was active, activate target window or default window */
|
||||
if (qs->active_window == s) {
|
||||
qs->active_window = s->target_window ? s->target_window : qs->first_window;
|
||||
if (qs->active_window)
|
||||
qe_check_buffer_file(qs->active_window->b, CBF_CHECK);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -7345,6 +7354,8 @@ void edit_close(EditState **sp)
|
|||
/* save current state for later window reattachment */
|
||||
switch_to_buffer(s, NULL);
|
||||
edit_detach(s);
|
||||
if (s->qs->key_ctx.grab_key_opaque == s)
|
||||
s->qs->key_ctx.grab_key_opaque = NULL;
|
||||
/* closing the window mode should have freed it already */
|
||||
qe_free_mode_data(s->mode_data);
|
||||
qe_free(&s->prompt);
|
||||
|
|
@ -9102,7 +9113,6 @@ int qe_load_file(EditState *s, const char *filename1, int lflags, int bflags)
|
|||
b = qe_find_buffer_filename(qs, filename);
|
||||
if (b != NULL) {
|
||||
switch_to_buffer(s, b);
|
||||
qe_check_buffer_file(b, CBF_CHECK);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -9368,14 +9378,14 @@ static void put_save_message(EditState *s, const char *filename, int nb)
|
|||
|
||||
void do_save_buffer(EditState *s)
|
||||
{
|
||||
if (qe_check_buffer_file(s->b, CBF_SAVE) == CBF_PROMPT)
|
||||
return;
|
||||
|
||||
if (!s->b->modified) {
|
||||
/* CG: This behaviour bugs me! */
|
||||
put_status(s, "(No changes need to be saved)");
|
||||
return;
|
||||
}
|
||||
if (qe_check_buffer_file(s->b, CBF_SAVE) == CBF_PROMPT)
|
||||
return;
|
||||
|
||||
put_save_message(s, s->b->filename, eb_save_buffer(s->b));
|
||||
}
|
||||
|
||||
|
|
@ -9399,11 +9409,16 @@ void do_write_region(EditState *s, const char *filename)
|
|||
eb_write_buffer(s->b, s->b->mark, s->offset, filename));
|
||||
}
|
||||
|
||||
static void qe_check_buffer_file_key(EditBuffer *b, int ch, int save)
|
||||
static void qe_check_buffer_file_key(QEmacsState *qs, EditBuffer *b, int ch, int save)
|
||||
{
|
||||
QEmacsState *qs = b->qs;
|
||||
EditState *s = qs->active_window;
|
||||
|
||||
if (!b) {
|
||||
qe_ungrab_keys(qs);
|
||||
put_error(s, "&Deleted");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (ch) {
|
||||
case KEY_CTRL('g'): /* abort */
|
||||
qe_ungrab_keys(qs);
|
||||
|
|
@ -9447,6 +9462,7 @@ static void qe_check_buffer_file_key(EditBuffer *b, int ch, int save)
|
|||
put_error(s, "Diff not supported");
|
||||
#else
|
||||
qe_ungrab_keys(qs);
|
||||
put_status(s, "");
|
||||
qe_diff_buffer_with_file(s, b);
|
||||
#endif
|
||||
break;
|
||||
|
|
@ -9477,14 +9493,14 @@ static void qe_check_buffer_file_key(EditBuffer *b, int ch, int save)
|
|||
qe_display(qs);
|
||||
}
|
||||
|
||||
static void qe_check_buffer_file_key_read(void *opaque, int ch)
|
||||
static void qe_check_buffer_file_key_read(QEmacsState *qs, void *opaque, int ch)
|
||||
{
|
||||
qe_check_buffer_file_key(opaque, ch, FALSE);
|
||||
qe_check_buffer_file_key(qs, opaque, ch, FALSE);
|
||||
}
|
||||
|
||||
static void qe_check_buffer_file_key_save(void *opaque, int ch)
|
||||
static void qe_check_buffer_file_key_save(QEmacsState *qs, void *opaque, int ch)
|
||||
{
|
||||
qe_check_buffer_file_key(opaque, ch, TRUE);
|
||||
qe_check_buffer_file_key(qs, opaque, ch, TRUE);
|
||||
}
|
||||
|
||||
int qe_check_buffer_file(EditBuffer *b, int mode)
|
||||
|
|
@ -9595,8 +9611,8 @@ typedef struct QuitState {
|
|||
QEmacsState *qs;
|
||||
} QuitState;
|
||||
|
||||
static void quit_examine_buffers(QuitState *is);
|
||||
static void quit_key(void *opaque, int ch);
|
||||
static void quit_examine_buffers(QEmacsState *qs, QuitState *is);
|
||||
static void quit_key(QEmacsState *qs, void *opaque, int ch);
|
||||
static void quit_confirm_cb(void *opaque, char *reply, CompletionDef *completion);
|
||||
|
||||
static void do_suspend_qemacs(EditState *s, int argval)
|
||||
|
|
@ -9628,13 +9644,12 @@ void do_exit_qemacs(EditState *s, int argval)
|
|||
|
||||
qe_stop_macro(qs);
|
||||
qe_grab_keys(qs, quit_key, is);
|
||||
quit_examine_buffers(is);
|
||||
quit_examine_buffers(qs, is);
|
||||
}
|
||||
|
||||
/* analyse next buffer and ask question if needed */
|
||||
static void quit_examine_buffers(QuitState *is)
|
||||
static void quit_examine_buffers(QEmacsState *qs, QuitState *is)
|
||||
{
|
||||
QEmacsState *qs = is->qs;
|
||||
EditBuffer *b;
|
||||
|
||||
while (is->b != NULL) {
|
||||
|
|
@ -9677,11 +9692,17 @@ static void quit_examine_buffers(QuitState *is)
|
|||
qe_free(&is);
|
||||
}
|
||||
|
||||
static void quit_key(void *opaque, int ch)
|
||||
static void quit_key(QEmacsState *qs, void *opaque, int ch)
|
||||
{
|
||||
QuitState *is = opaque;
|
||||
EditBuffer *b;
|
||||
|
||||
if (!is || !(b = qe_check_buffer(qs, &is->b))) {
|
||||
qe_ungrab_keys(qs);
|
||||
put_error(qs->active_window, "&Deleted");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (ch) {
|
||||
case 'y':
|
||||
case ' ':
|
||||
|
|
@ -9705,20 +9726,19 @@ static void quit_key(void *opaque, int ch)
|
|||
/* save current and exit */
|
||||
is->state = QS_NOSAVE;
|
||||
do_save:
|
||||
b = is->b;
|
||||
eb_save_buffer(b);
|
||||
break;
|
||||
case KEY_CTRL('g'):
|
||||
/* abort */
|
||||
qe_ungrab_keys(is->qs);
|
||||
put_error(is->qs->active_window, "&Quit");
|
||||
qe_ungrab_keys(qs);
|
||||
put_error(qs->active_window, "&Quit");
|
||||
return;
|
||||
default:
|
||||
/* get another key */
|
||||
return;
|
||||
}
|
||||
is->b = is->b->next;
|
||||
quit_examine_buffers(is);
|
||||
is->b = b->next;
|
||||
quit_examine_buffers(qs, is);
|
||||
}
|
||||
|
||||
static void quit_confirm_cb(qe__unused__ void *opaque,
|
||||
|
|
@ -9972,7 +9992,6 @@ void do_other_window(EditState *s)
|
|||
if (e->flags & WF_MINIBUF)
|
||||
edit_invalidate(e, 0);
|
||||
s->qs->active_window = e;
|
||||
qe_check_buffer_file(e->b, CBF_CHECK);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -9981,7 +10000,6 @@ void do_previous_window(EditState *s)
|
|||
EditState *e = get_previous_window(s, 0, 0);
|
||||
if (e) {
|
||||
s->qs->active_window = e;
|
||||
qe_check_buffer_file(e->b, CBF_CHECK);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -10056,8 +10074,6 @@ void do_delete_window(EditState *s, int force)
|
|||
}
|
||||
if (qs->active_window == s) {
|
||||
qs->active_window = e1 ? e1 : qs->first_window;
|
||||
if (qs->active_window)
|
||||
qe_check_buffer_file(qs->active_window->b, CBF_CHECK);
|
||||
}
|
||||
edit_close(&s);
|
||||
if (qs->first_window)
|
||||
|
|
|
|||
4
qe.h
4
qe.h
|
|
@ -249,7 +249,7 @@ static inline QEEvent *qe_event_clear(QEEvent *ev) {
|
|||
void qe_handle_event(QEmacsState *qs, QEEvent *ev);
|
||||
/* CG: Should optionally attach grab to a window */
|
||||
/* CG: Should deal with opaque object life cycle */
|
||||
void qe_grab_keys(QEmacsState *qs, void (*cb)(void *opaque, int key), void *opaque);
|
||||
void qe_grab_keys(QEmacsState *qs, void (*cb)(QEmacsState *qs, void *opaque, int key), void *opaque);
|
||||
void qe_ungrab_keys(QEmacsState *qs);
|
||||
KeyDef *qe_find_binding(unsigned int *keys, int nb_keys, KeyDef *kd, int exact);
|
||||
KeyDef *qe_find_current_binding(QEmacsState *qs, unsigned int *keys, int nb_keys, ModeDef *m, int exact);
|
||||
|
|
@ -985,7 +985,7 @@ typedef struct QEKeyContext {
|
|||
int is_escape;
|
||||
int nb_keys;
|
||||
int describe_key; /* if true, the following command is only displayed */
|
||||
void (*grab_key_cb)(void *opaque, int key);
|
||||
void (*grab_key_cb)(QEmacsState *qs, void *opaque, int key);
|
||||
void *grab_key_opaque;
|
||||
unsigned int keys[MAX_KEYS];
|
||||
char buf[128];
|
||||
|
|
|
|||
33
search.c
33
search.c
|
|
@ -2,7 +2,7 @@
|
|||
* Incremental search and replace for QEmacs.
|
||||
*
|
||||
* Copyright (c) 2000-2002 Fabrice Bellard.
|
||||
* Copyright (c) 2000-2024 Charlie Gordon.
|
||||
* Copyright (c) 2000-2026 Charlie Gordon.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
@ -809,25 +809,31 @@ static void isearch_exit(EditState *s, int key) {
|
|||
}
|
||||
}
|
||||
|
||||
static void isearch_key(void *opaque, int key) {
|
||||
static void isearch_key(QEmacsState *qs, void *opaque, int key) {
|
||||
ISearchState *is = opaque;
|
||||
QEmacsState *qs = is->s->qs;
|
||||
EditState *s;
|
||||
unsigned int keys[1] = { key };
|
||||
|
||||
if (!is || !(s = qe_check_window(qs, &is->s))) {
|
||||
qe_ungrab_keys(qs);
|
||||
put_error(qs->active_window, "&Deleted");
|
||||
return;
|
||||
}
|
||||
|
||||
if (is->quoting) {
|
||||
is->quoting = 0;
|
||||
if (!KEY_IS_SPECIAL(key)) {
|
||||
isearch_printing_char(is->s, key);
|
||||
isearch_printing_char(s, key);
|
||||
}
|
||||
} else {
|
||||
KeyDef *kd = qe_find_binding(keys, 1, isearch_mode.first_key, 1);
|
||||
if (kd) {
|
||||
exec_command(is->s, kd->cmd, NO_ARG, key);
|
||||
exec_command(s, kd->cmd, NO_ARG, key);
|
||||
} else {
|
||||
if (KEY_IS_SPECIAL(key) || KEY_IS_CONTROL(key)) {
|
||||
isearch_exit(is->s, key);
|
||||
isearch_exit(s, key);
|
||||
} else {
|
||||
isearch_printing_char(is->s, key);
|
||||
isearch_printing_char(s, key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1123,11 +1129,18 @@ static void query_replace_run(QueryReplaceState *is)
|
|||
put_status(s, "&%s", out->buf);
|
||||
}
|
||||
|
||||
static void query_replace_key(void *opaque, int key)
|
||||
static void query_replace_key(QEmacsState *qs, void *opaque, int key)
|
||||
{
|
||||
QueryReplaceState *is = opaque;
|
||||
EditState *s = is->s;
|
||||
QEmacsState *qs = s->qs;
|
||||
EditState *s;
|
||||
|
||||
if (!is || !(s = qe_check_window(qs, &is->s))) {
|
||||
qe_ungrab_keys(qs);
|
||||
qe_free(&is);
|
||||
qe_display(qs);
|
||||
put_error(qs->active_window, "&Deleted");
|
||||
return;
|
||||
}
|
||||
|
||||
if (qe_check_window(qs, &is->help_window)) {
|
||||
do_delete_window(is->help_window, 0);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue