reordered KEY_xxx definitions
added KEY_DEL=127 (formerly KEY_BACKSPACE) added KEY_BS=8 C-H to handle control-h as backspace on some ttys fixed KEY_F6 thru KEY_F12 (were off by one) added strtokeys() to convert a string with key names to a key buffer added define-kbd-macro() from key string added execute-macro-keys() to execute commands from a key string improved qe_key_process(). changed method to update shell cursor : tty_update_cursor disabled shell_display_hook() used instead greatly improved shell buffer behaviour, charset handling. much improved tty input handling : support more key combinations and modes. added missing charset declarations in qe.h added borders_invalid and complete_refresh window flags made C-L completely refresh display moved window border display to separate function changed edit_display() to allow complete redisplay even with popups fixed window delete crash bugs by improving consistency with edit_attach and edit_detach.
This commit is contained in:
parent
8d2cbbb4cc
commit
8fac0ab42e
9 changed files with 567 additions and 226 deletions
|
|
@ -102,6 +102,7 @@ typedef struct QEDisplay {
|
|||
int x, int y, int w, int h);
|
||||
void (*dpy_selection_activate)(QEditScreen *s);
|
||||
void (*dpy_selection_request)(QEditScreen *s);
|
||||
void (*dpy_invalidate)(void);
|
||||
/* bitmap support */
|
||||
int (*dpy_bmp_alloc)(QEditScreen *s, QEBitmap *b);
|
||||
void (*dpy_bmp_free)(QEditScreen *s, QEBitmap *b);
|
||||
|
|
|
|||
235
qe.c
235
qe.c
|
|
@ -329,22 +329,14 @@ void command_completion(StringArray *cs, const char *input)
|
|||
|
||||
void do_global_set_key(EditState *s, const char *keystr, const char *cmd_name)
|
||||
{
|
||||
int key, nb_keys;
|
||||
int nb_keys;
|
||||
unsigned int keys[MAX_KEYS];
|
||||
const char *p;
|
||||
CmdDef *d;
|
||||
|
||||
p = keystr;
|
||||
nb_keys = 0;
|
||||
for(;;) {
|
||||
skip_spaces(&p);
|
||||
if (*p == '\0')
|
||||
break;
|
||||
key = strtokey(&p);
|
||||
keys[nb_keys++] = key;
|
||||
if (nb_keys >= MAX_KEYS)
|
||||
break;
|
||||
}
|
||||
nb_keys = strtokeys(keystr, keys, MAX_KEYS);
|
||||
if (!nb_keys)
|
||||
return;
|
||||
|
||||
d = qe_find_cmd(cmd_name);
|
||||
if (!d)
|
||||
return;
|
||||
|
|
@ -1681,6 +1673,7 @@ void do_insert_file(EditState *s, const char *filename);
|
|||
void do_save(EditState *s, int save_as);
|
||||
void do_isearch(EditState *s, int dir);
|
||||
void do_refresh(EditState *s);
|
||||
void do_refresh_complete(EditState *s);
|
||||
|
||||
/* compute string for the first part of the mode line (flags,
|
||||
filename, modename) */
|
||||
|
|
@ -1767,6 +1760,45 @@ void display_mode_line(EditState *s)
|
|||
}
|
||||
}
|
||||
|
||||
void display_window_borders(EditState *e)
|
||||
{
|
||||
QEmacsState *qs = e->qe_state;
|
||||
|
||||
if (e->borders_invalid) {
|
||||
if (e->flags & (WF_POPUP | WF_RSEPARATOR)) {
|
||||
CSSRect rect;
|
||||
QEColor color;
|
||||
|
||||
rect.x1 = 0;
|
||||
rect.y1 = 0;
|
||||
rect.x2 = qs->width;
|
||||
rect.y2 = qs->height;
|
||||
set_clip_rectangle(qs->screen, &rect);
|
||||
color = qe_styles[QE_STYLE_WINDOW_BORDER].bg_color;
|
||||
if (e->flags & WF_POPUP) {
|
||||
fill_rectangle(qs->screen,
|
||||
e->x1, e->y1,
|
||||
qs->border_width, e->y2 - e->y1, color);
|
||||
fill_rectangle(qs->screen,
|
||||
e->x2 - qs->border_width, e->y1,
|
||||
qs->border_width, e->y2 - e->y1, color);
|
||||
fill_rectangle(qs->screen,
|
||||
e->x1, e->y1,
|
||||
e->x2 - e->x1, qs->border_width, color);
|
||||
fill_rectangle(qs->screen,
|
||||
e->x1, e->y2 - qs->border_width,
|
||||
e->x2 - e->x1, qs->border_width, color);
|
||||
}
|
||||
if (e->flags & WF_RSEPARATOR) {
|
||||
fill_rectangle(qs->screen,
|
||||
e->x2 - qs->separator_width, e->y1,
|
||||
qs->separator_width, e->y2 - e->y1, color);
|
||||
}
|
||||
}
|
||||
e->borders_invalid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* compute style */
|
||||
static void apply_style(QEStyleDef *style, int style_index)
|
||||
{
|
||||
|
|
@ -3320,6 +3352,7 @@ void window_display(EditState *s)
|
|||
s->mode->display(s);
|
||||
|
||||
display_mode_line(s);
|
||||
display_window_borders(s);
|
||||
}
|
||||
|
||||
/* display all windows */
|
||||
|
|
@ -3335,23 +3368,34 @@ void edit_display(QEmacsState *qs)
|
|||
s->mode->display_hook(s);
|
||||
}
|
||||
|
||||
/* first display popups and minibuf */
|
||||
/* count popups */
|
||||
/* CG: maybe a separate list for popups? */
|
||||
has_popups = 0;
|
||||
for (s = qs->first_window; s != NULL; s = s->next_window) {
|
||||
if (s->flags & WF_POPUP) {
|
||||
window_display(s);
|
||||
has_popups = 1;
|
||||
} else if (s->minibuf) {
|
||||
window_display(s);
|
||||
}
|
||||
}
|
||||
|
||||
if (!has_popups) {
|
||||
for(s = qs->first_window; s != NULL; s = s->next_window) {
|
||||
if (!s->minibuf)
|
||||
window_display(s);
|
||||
}
|
||||
/* refresh normal windows and minibuf with popup kludge */
|
||||
for (s = qs->first_window; s != NULL; s = s->next_window) {
|
||||
if (!(s->flags & WF_POPUP) &&
|
||||
(s->minibuf || !has_popups || qs->complete_refresh)) {
|
||||
window_display(s);
|
||||
}
|
||||
}
|
||||
/* refresh popups if any */
|
||||
if (has_popups) {
|
||||
for (s = qs->first_window; s != NULL; s = s->next_window) {
|
||||
if (s->flags & WF_POPUP) {
|
||||
if (qs->complete_refresh)
|
||||
/* refresh frame */;
|
||||
window_display(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
qs->complete_refresh = 0;
|
||||
}
|
||||
|
||||
void do_universal_argument(EditState *s)
|
||||
|
|
@ -3442,6 +3486,46 @@ void do_call_macro(EditState *s)
|
|||
}
|
||||
}
|
||||
|
||||
void do_execute_macro_keys(EditState *s, const char *keys)
|
||||
{
|
||||
int key;
|
||||
const char *p;
|
||||
|
||||
p = keys;
|
||||
for (;;) {
|
||||
skip_spaces(&p);
|
||||
if (*p == '\0')
|
||||
break;
|
||||
key = strtokey(&p);
|
||||
qe_key_process(key);
|
||||
}
|
||||
}
|
||||
|
||||
void do_define_kbd_macro(EditState *s, const char *name, const char *keys,
|
||||
const char *keystr)
|
||||
{
|
||||
CmdDef *def;
|
||||
int size;
|
||||
char *macro_name, *p;
|
||||
|
||||
size = strlen(name) + 1;
|
||||
macro_name = malloc(size + 2);
|
||||
memcpy(macro_name, name, size);
|
||||
p = macro_name + size;
|
||||
*p++ = 'S';
|
||||
*p++ = '\0';
|
||||
|
||||
def = malloc(2 * sizeof(CmdDef));
|
||||
memset(def, 0, sizeof(CmdDef) * 2);
|
||||
def->key = def->alt_key = KEY_NONE;
|
||||
def->name = macro_name;
|
||||
def->action.func = do_execute_macro_keys;
|
||||
def->val = strdup(keystr);
|
||||
|
||||
qe_register_cmd_table(def, NULL);
|
||||
do_global_set_key(s, keystr, name);
|
||||
}
|
||||
|
||||
#define MACRO_KEY_INCR 64
|
||||
|
||||
static void macro_add_key(int key)
|
||||
|
|
@ -3518,7 +3602,7 @@ static void qe_key_process(int key)
|
|||
EditState *s;
|
||||
KeyDef *kd;
|
||||
CmdDef *d;
|
||||
char buf1[32];
|
||||
char buf1[128];
|
||||
int len;
|
||||
|
||||
if (qs->defining_macro) {
|
||||
|
|
@ -3544,14 +3628,14 @@ static void qe_key_process(int key)
|
|||
|
||||
/* special case for escape : we transform it as meta so
|
||||
that unix users are happy ! */
|
||||
/* CG: should allow for other key compositions, such as
|
||||
* diacritics, and compositions of more than 2 keys
|
||||
*/
|
||||
if (key == KEY_ESC) {
|
||||
c->is_escape = 1;
|
||||
goto next;
|
||||
} else if (c->is_escape) {
|
||||
if (c->nb_keys >= 2) {
|
||||
c->nb_keys--;
|
||||
c->keys[c->nb_keys - 1] = KEY_META(key);
|
||||
}
|
||||
compose_keys(c->keys, &c->nb_keys);
|
||||
c->is_escape = 0;
|
||||
}
|
||||
|
||||
|
|
@ -3595,8 +3679,15 @@ static void qe_key_process(int key)
|
|||
}
|
||||
}
|
||||
}
|
||||
qe_key_init();
|
||||
if (!c->describe_key)
|
||||
/* CG: should beep */;
|
||||
|
||||
put_status(s, "No command on %s",
|
||||
keys_to_str(buf1, sizeof(buf1), c->keys, c->nb_keys));
|
||||
c->describe_key = 0;
|
||||
qe_key_init();
|
||||
dpy_flush(&global_screen);
|
||||
return;
|
||||
} else if (c->nb_keys == kd->nb_keys) {
|
||||
exec_cmd:
|
||||
d = kd->cmd;
|
||||
|
|
@ -3615,7 +3706,6 @@ static void qe_key_process(int key)
|
|||
}
|
||||
}
|
||||
if (c->describe_key) {
|
||||
char buf1[128];
|
||||
put_status(s, "%s runs the command %s",
|
||||
keys_to_str(buf1, sizeof(buf1), c->keys, c->nb_keys),
|
||||
d->name);
|
||||
|
|
@ -3632,6 +3722,7 @@ static void qe_key_process(int key)
|
|||
next:
|
||||
/* display key pressed */
|
||||
if (!s->minibuf) {
|
||||
/* Should print argument if any in a more readable way */
|
||||
keytostr(buf1, sizeof(buf1), key);
|
||||
len = strlen(c->buf);
|
||||
if (len >= 1)
|
||||
|
|
@ -3806,6 +3897,7 @@ static void compute_client_area(EditState *s)
|
|||
EditState *edit_new(EditBuffer *b,
|
||||
int x1, int y1, int width, int height, int flags)
|
||||
{
|
||||
/* b may be NULL ??? */
|
||||
EditState *s;
|
||||
QEmacsState *qs = &qe_state;
|
||||
|
||||
|
|
@ -3829,6 +3921,30 @@ EditState *edit_new(EditBuffer *b,
|
|||
return s;
|
||||
}
|
||||
|
||||
/* detach the window from the window tree. */
|
||||
void edit_detach(EditState *s)
|
||||
{
|
||||
QEmacsState *qs = s->qe_state;
|
||||
EditState **ep;
|
||||
|
||||
for (ep = &qs->first_window; *ep; ep = &(*ep)->next_window) {
|
||||
if (*ep == s) {
|
||||
*ep = s->next_window;
|
||||
s->next_window = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (qs->active_window == s)
|
||||
qs->active_window = qs->first_window;
|
||||
}
|
||||
|
||||
/* attach the window to the window list. */
|
||||
void edit_attach(EditState *s, EditState **ep)
|
||||
{
|
||||
s->next_window = *ep;
|
||||
*ep = s;
|
||||
}
|
||||
|
||||
/* close the edit window. If it is active, find another active
|
||||
window. If the buffer is only referenced by this window, then save
|
||||
in the buffer all the window state so that it can be recovered. */
|
||||
|
|
@ -4222,6 +4338,7 @@ void minibuffer_edit(const char *input, const char *prompt,
|
|||
|
||||
s = edit_new(b, 0, qs->screen->height - qs->status_height,
|
||||
qs->screen->width, qs->status_height, 0);
|
||||
/* Should insert at end of window list */
|
||||
do_set_mode(s, &minibuffer_mode, NULL);
|
||||
s->prompt = strdup(prompt);
|
||||
s->minibuf = 1;
|
||||
|
|
@ -4274,6 +4391,7 @@ void do_less_quit(EditState *s)
|
|||
QEmacsState *qs = s->qe_state;
|
||||
EditBuffer *b;
|
||||
|
||||
/* CG: should verify that popup_saved_active still exists */
|
||||
qs->active_window = popup_saved_active;
|
||||
b = s->b;
|
||||
edit_close(s);
|
||||
|
|
@ -5065,7 +5183,8 @@ static void isearch_key(void *opaque, int ch)
|
|||
int i, j;
|
||||
|
||||
switch (ch) {
|
||||
case KEY_BACKSPACE:
|
||||
case KEY_DEL:
|
||||
case KEY_BS: /* Should test actual binding of KEY_BS */
|
||||
if (is->pos > 0)
|
||||
is->pos--;
|
||||
break;
|
||||
|
|
@ -5306,6 +5425,7 @@ static void do_query_replace(EditState *s,
|
|||
|
||||
void do_doctor(EditState *s)
|
||||
{
|
||||
/* Should show keys? */
|
||||
put_status(s, "Hello, how are you ?");
|
||||
}
|
||||
|
||||
|
|
@ -5334,6 +5454,11 @@ void do_refresh(EditState *s1)
|
|||
int new_status_height, new_mode_line_height, content_height;
|
||||
int width, height;
|
||||
|
||||
if (qs->complete_refresh) {
|
||||
if (qs->screen->dpy.dpy_invalidate)
|
||||
qs->screen->dpy.dpy_invalidate();
|
||||
}
|
||||
|
||||
/* recompute various dimensions */
|
||||
if (qs->screen->media & CSS_MEDIA_TTY) {
|
||||
qs->separator_width = 1;
|
||||
|
|
@ -5396,41 +5521,21 @@ void do_refresh(EditState *s1)
|
|||
/* invalidate all the edit windows and draw borders */
|
||||
for(e = qs->first_window; e != NULL; e = e->next_window) {
|
||||
edit_invalidate(e);
|
||||
if (e->flags & (WF_POPUP | WF_RSEPARATOR)) {
|
||||
CSSRect rect;
|
||||
QEColor color;
|
||||
rect.x1 = 0;
|
||||
rect.y1 = 0;
|
||||
rect.x2 = qs->width;
|
||||
rect.y2 = qs->height;
|
||||
set_clip_rectangle(qs->screen, &rect);
|
||||
color = qe_styles[QE_STYLE_WINDOW_BORDER].bg_color;
|
||||
if (e->flags & WF_POPUP) {
|
||||
fill_rectangle(qs->screen,
|
||||
e->x1, e->y1,
|
||||
qs->border_width, e->y2 - e->y1, color);
|
||||
fill_rectangle(qs->screen,
|
||||
e->x2 - qs->border_width, e->y1,
|
||||
qs->border_width, e->y2 - e->y1, color);
|
||||
fill_rectangle(qs->screen,
|
||||
e->x1, e->y1,
|
||||
e->x2 - e->x1, qs->border_width, color);
|
||||
fill_rectangle(qs->screen,
|
||||
e->x1, e->y2 - qs->border_width,
|
||||
e->x2 - e->x1, qs->border_width, color);
|
||||
}
|
||||
if (e->flags & WF_RSEPARATOR) {
|
||||
fill_rectangle(qs->screen,
|
||||
e->x2 - qs->separator_width, e->y1,
|
||||
qs->separator_width, e->y2 - e->y1, color);
|
||||
}
|
||||
}
|
||||
e->borders_invalid = 1;
|
||||
}
|
||||
/* invalidate status line */
|
||||
qs->status_shadow[0] = '\0';
|
||||
put_status(NULL, " ");
|
||||
}
|
||||
|
||||
void do_refresh_complete(EditState *s)
|
||||
{
|
||||
QEmacsState *qs = s->qe_state;
|
||||
|
||||
qs->complete_refresh = 1;
|
||||
do_refresh(s);
|
||||
}
|
||||
|
||||
void do_other_window(EditState *s)
|
||||
{
|
||||
QEmacsState *qs = s->qe_state;
|
||||
|
|
@ -5510,6 +5615,8 @@ void do_delete_window(EditState *s, int force)
|
|||
if (e)
|
||||
compute_client_area(e);
|
||||
}
|
||||
if (qs->active_window == s)
|
||||
qs->active_window = e ? e : qs->first_window;
|
||||
edit_close(s);
|
||||
if (qs->first_window)
|
||||
do_refresh(qs->first_window);
|
||||
|
|
@ -5539,6 +5646,7 @@ void do_delete_other_windows(EditState *s)
|
|||
/* XXX: add minimum size test and refuse to split if reached */
|
||||
void do_split_window(EditState *s, int horiz)
|
||||
{
|
||||
QEmacsState *qs = s->qe_state;
|
||||
EditState *e;
|
||||
int x, y;
|
||||
|
||||
|
|
@ -5564,6 +5672,13 @@ void do_split_window(EditState *s, int horiz)
|
|||
return;
|
||||
s->y2 = y;
|
||||
}
|
||||
/* insert in the window list after current window */
|
||||
edit_detach(e);
|
||||
edit_attach(e, &s->next_window);
|
||||
|
||||
if (qs->flag_split_window_change_focus)
|
||||
qs->active_window = e;
|
||||
|
||||
compute_client_area(s);
|
||||
do_refresh(s);
|
||||
}
|
||||
|
|
@ -5638,7 +5753,7 @@ void do_describe_bindings(EditState *s)
|
|||
b->flags |= BF_READONLY;
|
||||
if (show) {
|
||||
show_popup(b);
|
||||
eb_free(b);
|
||||
//eb_free(b);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
133
qe.h
133
qe.h
|
|
@ -92,7 +92,9 @@ int ustristart(const unsigned int *str, const char *val, const unsigned int **pt
|
|||
void css_strtolower(char *buf, int buf_size);
|
||||
|
||||
void get_str(const char **pp, char *buf, int buf_size, const char *stop);
|
||||
int compose_keys(int *keys, int *nb_keys);
|
||||
int strtokey(const char **pp);
|
||||
int strtokeys(const char *keystr, unsigned int *keys, int max_keys);
|
||||
void keytostr(char *buf, int buf_size, int key);
|
||||
int css_define_color(const char *name, const char *value);
|
||||
int css_get_color(int *color_ptr, const char *p);
|
||||
|
|
@ -209,8 +211,32 @@ typedef struct QECharset {
|
|||
struct QECharset *next;
|
||||
} QECharset;
|
||||
|
||||
extern QECharset charset_utf8, charset_8859_1; /* predefined charsets */
|
||||
extern QECharset *first_charset;
|
||||
extern QECharset charset_utf8, charset_8859_1; /* predefined charsets */
|
||||
extern QECharset charset_8859_2;
|
||||
extern QECharset charset_cp1125;
|
||||
extern QECharset charset_cp737;
|
||||
extern QECharset charset_koi8_r;
|
||||
extern QECharset charset_8859_4;
|
||||
extern QECharset charset_cp1250;
|
||||
extern QECharset charset_cp850;
|
||||
extern QECharset charset_koi8_u;
|
||||
extern QECharset charset_viscii;
|
||||
extern QECharset charset_8859_13;
|
||||
extern QECharset charset_8859_5;
|
||||
extern QECharset charset_cp1251;
|
||||
extern QECharset charset_cp852;
|
||||
extern QECharset charset_mac_lat2;
|
||||
extern QECharset charset_8859_15;
|
||||
extern QECharset charset_8859_7;
|
||||
extern QECharset charset_cp1257;
|
||||
extern QECharset charset_cp866;
|
||||
extern QECharset charset_macroman;
|
||||
extern QECharset charset_8859_16;
|
||||
extern QECharset charset_8859_9;
|
||||
extern QECharset charset_cp437;
|
||||
extern QECharset charset_kamen;
|
||||
extern QECharset charset_tcvn5712;
|
||||
|
||||
typedef struct CharsetDecodeState {
|
||||
/* 256 ushort table for hyper fast decoding */
|
||||
|
|
@ -286,50 +312,63 @@ enum QEEventType {
|
|||
QE_SELECTION_CLEAR_EVENT, /* request selection clear (X11 type selection) */
|
||||
};
|
||||
|
||||
#define KEY_META(c) ((c) | 0xe000)
|
||||
#define KEY_ESC1(c) ((c) | 0xe100)
|
||||
#define KEY_CTRLX(c) ((c) | 0xe200)
|
||||
#define KEY_CTRL(c) ((c) & 0x001f)
|
||||
#define KEY_META(c) ((c) | 0xe000)
|
||||
#define KEY_ESC1(c) ((c) | 0xe100)
|
||||
#define KEY_CTRLX(c) ((c) | 0xe200)
|
||||
#define KEY_CTRLXRET(c) ((c) | 0xe300)
|
||||
#define KEY_CTRLH(c) ((c) | 0xe500)
|
||||
#define KEY_CTRL(c) ((c) & 0x1f)
|
||||
#define KEY_UP KEY_ESC1('A')
|
||||
#define KEY_DOWN KEY_ESC1('B')
|
||||
#define KEY_RIGHT KEY_ESC1('C')
|
||||
#define KEY_LEFT KEY_ESC1('D')
|
||||
#define KEY_CTRL_UP KEY_ESC1('a')
|
||||
#define KEY_CTRL_DOWN KEY_ESC1('b')
|
||||
#define KEY_CTRL_RIGHT KEY_ESC1('c')
|
||||
#define KEY_CTRL_LEFT KEY_ESC1('d')
|
||||
#define KEY_CTRL_HOME 0xe402
|
||||
#define KEY_CTRL_END 0xe403
|
||||
#define KEY_TAB KEY_CTRL('i')
|
||||
#define KEY_SHIFT_TAB 0xe404
|
||||
#define KEY_F1 KEY_ESC1(11)
|
||||
#define KEY_F2 KEY_ESC1(12)
|
||||
#define KEY_F3 KEY_ESC1(13)
|
||||
#define KEY_F4 KEY_ESC1(14)
|
||||
#define KEY_F5 KEY_ESC1(15)
|
||||
#define KEY_F6 KEY_ESC1(16)
|
||||
#define KEY_F7 KEY_ESC1(17)
|
||||
#define KEY_F8 KEY_ESC1(18)
|
||||
#define KEY_F9 KEY_ESC1(19)
|
||||
#define KEY_F10 KEY_ESC1(20)
|
||||
#define KEY_F11 KEY_ESC1(21)
|
||||
#define KEY_F12 KEY_ESC1(22)
|
||||
#define KEY_BACKSPACE 127
|
||||
#define KEY_INSERT KEY_ESC1(2)
|
||||
#define KEY_DELETE KEY_ESC1(3)
|
||||
#define KEY_PAGEUP KEY_ESC1(5)
|
||||
#define KEY_PAGEDOWN KEY_ESC1(6)
|
||||
#define KEY_HOME KEY_ESC1(7)
|
||||
#define KEY_END KEY_ESC1(8)
|
||||
#define KEY_REFRESH KEY_CTRL('l')
|
||||
#define KEY_RET 0x000d
|
||||
#define KEY_ESC 0x001b
|
||||
#define KEY_SPC 0x0020
|
||||
#define KEY_NONE 0xffff
|
||||
#define KEY_DEFAULT 0xe401 /* to handle all non special keys */
|
||||
#define KEY_SPECIAL(c) (((c) >= 0xe000 && (c) < 0xf000) || ((c) >= 0 && (c) < 32))
|
||||
#define KEY_CTRLH(c) ((c) | 0xe500)
|
||||
#define KEY_SPECIAL(c) (((c) >= 0xe000 && (c) < 0xf000) || ((c) >= 0 && (c) < 32))
|
||||
|
||||
#define KEY_NONE 0xffff
|
||||
#define KEY_TAB KEY_CTRL('i')
|
||||
#define KEY_RET KEY_CTRL('m')
|
||||
#define KEY_REFRESH KEY_CTRL('l')
|
||||
#define KEY_ESC KEY_CTRL('[')
|
||||
#define KEY_SPC 0x0020
|
||||
#define KEY_DEL 127 // kbs
|
||||
#define KEY_BS KEY_CTRL('h') // kbs
|
||||
|
||||
#define KEY_DEFAULT 0xe401 /* to handle all non special keys */
|
||||
#define KEY_UP KEY_ESC1('A') // kcuu1
|
||||
#define KEY_DOWN KEY_ESC1('B') // kcud1
|
||||
#define KEY_RIGHT KEY_ESC1('C') // kcuf1
|
||||
#define KEY_LEFT KEY_ESC1('D') // kcub1
|
||||
#define KEY_CTRL_UP KEY_ESC1('a')
|
||||
#define KEY_CTRL_DOWN KEY_ESC1('b')
|
||||
#define KEY_CTRL_RIGHT KEY_ESC1('c')
|
||||
#define KEY_CTRL_LEFT KEY_ESC1('d')
|
||||
#define KEY_CTRL_END KEY_ESC1('f')
|
||||
#define KEY_CTRL_HOME KEY_ESC1('h')
|
||||
#define KEY_CTRL_PAGEUP KEY_ESC1('i')
|
||||
#define KEY_CTRL_PAGEDOWN KEY_ESC1('j')
|
||||
#define KEY_SHIFT_TAB KEY_ESC1('Z') // kcbt
|
||||
#define KEY_HOME KEY_ESC1(1) // khome
|
||||
#define KEY_INSERT KEY_ESC1(2) // kich1
|
||||
#define KEY_DELETE KEY_ESC1(3) // kdch1
|
||||
#define KEY_END KEY_ESC1(4) // kend
|
||||
#define KEY_PAGEUP KEY_ESC1(5) // kpp
|
||||
#define KEY_PAGEDOWN KEY_ESC1(6) // knp
|
||||
#define KEY_F1 KEY_ESC1(11)
|
||||
#define KEY_F2 KEY_ESC1(12)
|
||||
#define KEY_F3 KEY_ESC1(13)
|
||||
#define KEY_F4 KEY_ESC1(14)
|
||||
#define KEY_F5 KEY_ESC1(15)
|
||||
#define KEY_F6 KEY_ESC1(17)
|
||||
#define KEY_F7 KEY_ESC1(18)
|
||||
#define KEY_F8 KEY_ESC1(19)
|
||||
#define KEY_F9 KEY_ESC1(20)
|
||||
#define KEY_F10 KEY_ESC1(21)
|
||||
#define KEY_F11 KEY_ESC1(23)
|
||||
#define KEY_F12 KEY_ESC1(24)
|
||||
#define KEY_F13 KEY_ESC1(25)
|
||||
#define KEY_F14 KEY_ESC1(26)
|
||||
#define KEY_F15 KEY_ESC1(28)
|
||||
#define KEY_F16 KEY_ESC1(29)
|
||||
#define KEY_F17 KEY_ESC1(31)
|
||||
#define KEY_F18 KEY_ESC1(32)
|
||||
#define KEY_F19 KEY_ESC1(33)
|
||||
#define KEY_F20 KEY_ESC1(34)
|
||||
|
||||
typedef struct QEKeyEvent {
|
||||
enum QEEventType type;
|
||||
|
|
@ -698,6 +737,7 @@ typedef struct EditState {
|
|||
produce the display */
|
||||
int display_invalid; /* true if the display was invalidated. Full
|
||||
redraw should be done */
|
||||
int borders_invalid; /* true if window borders should be redrawn */
|
||||
int show_selection; /* if true, the selection is displayed */
|
||||
/* display area info */
|
||||
int width, height;
|
||||
|
|
@ -838,8 +878,10 @@ typedef struct QEmacsState {
|
|||
int separator_width;
|
||||
/* full screen state */
|
||||
int hide_status; /* true if status should be hidden */
|
||||
int complete_refresh;
|
||||
int is_full_screen;
|
||||
/* commands */
|
||||
int flag_split_window_change_focus;
|
||||
void *last_cmd_func; /* last executed command function call */
|
||||
/* keyboard macros */
|
||||
int defining_macro;
|
||||
|
|
@ -1082,6 +1124,8 @@ void do_find_window(EditState *s, int key);
|
|||
|
||||
/* window handling */
|
||||
void edit_close(EditState *s);
|
||||
void edit_detach(EditState *s);
|
||||
void edit_append(EditState *s, EditState *e);
|
||||
EditState *edit_new(EditBuffer *b,
|
||||
int x1, int y1, int width, int height, int flags);
|
||||
void do_refresh(EditState *s);
|
||||
|
|
@ -1106,6 +1150,7 @@ void do_char(EditState *s, int key);
|
|||
void do_switch_to_buffer(EditState *s, const char *bufname);;
|
||||
void do_set_mode(EditState *s, ModeDef *m, ModeSavedData *saved_data);
|
||||
void text_move_left_right_visual(EditState *s, int dir);
|
||||
void text_move_word_left_right(EditState *s, int dir);
|
||||
void text_move_up_down(EditState *s, int dir);
|
||||
void text_scroll_up_down(EditState *s, int dir);
|
||||
void text_write_char(EditState *s, int key);
|
||||
|
|
|
|||
12
qeconfig.h
12
qeconfig.h
|
|
@ -16,10 +16,10 @@ CmdDef basic_commands[] = {
|
|||
CMD1( KEY_CTRL('z'), KEY_NONE, "scroll-up-one", do_scroll_up_down, 1 )
|
||||
CMD0( KEY_HOME, KEY_CTRL('a'), "beginning-of-line", do_bol)
|
||||
CMD0( KEY_END, KEY_CTRL('e'), "end-of-line", do_eol)
|
||||
CMD0( KEY_ESC1(2), KEY_NONE, "overwrite-mode", do_insert)
|
||||
CMD0( KEY_INSERT, KEY_NONE, "overwrite-mode", do_insert)
|
||||
CMD0( KEY_CTRL('d'), KEY_DELETE, "delete-char", do_delete_char)
|
||||
CMD0( 127, KEY_NONE, "backward-delete-char", do_backspace)
|
||||
CMD1( KEY_META(KEY_BACKSPACE) , KEY_NONE,
|
||||
CMD1( KEY_META(KEY_DEL) , KEY_META(KEY_BS),
|
||||
"backward-delete-word", do_delete_word, -1)
|
||||
CMD1( KEY_META('d') , KEY_NONE, "delete-word", do_delete_word, 1)
|
||||
CMD1( KEY_CTRL('k'), KEY_NONE, "kill-line", do_kill_region, 2 )
|
||||
|
|
@ -59,7 +59,7 @@ CmdDef basic_commands[] = {
|
|||
"s{Query replace: }|search|s{With: }|replace|")
|
||||
CMD0( KEY_CTRLX('u'), KEY_CTRL('_'), "undo", do_undo)
|
||||
CMD0( KEY_RET, KEY_NONE, "newline", do_return)
|
||||
CMD0( KEY_CTRL('l'), KEY_NONE, "refresh", do_refresh)
|
||||
CMD0( KEY_CTRL('l'), KEY_NONE, "refresh", do_refresh_complete)
|
||||
CMD_( KEY_META('g'), KEY_NONE, "goto-line", do_goto_line, "i{Goto line: }")
|
||||
CMD_( KEY_NONE, KEY_NONE, "goto-char", do_goto_char, "i{Goto char: }")
|
||||
CMD0( KEY_CTRLX(KEY_CTRL('q')), KEY_NONE, "vc-toggle-read-only",
|
||||
|
|
@ -80,8 +80,10 @@ CmdDef basic_commands[] = {
|
|||
CMD0( KEY_CTRLX('('), KEY_NONE, "start-kbd-macro", do_start_macro)
|
||||
CMD0( KEY_CTRLX(')'), KEY_NONE, "end-kbd-macro", do_end_macro)
|
||||
CMD0( KEY_CTRLX('e'), KEY_NONE, "call-last-kbd-macro", do_call_macro)
|
||||
CMD_( KEY_NONE, KEY_NONE, "define-kbd-macro", do_define_kbd_macro,
|
||||
"s{Macro name: }[command]s{Macro keys: }s{Bind to key: }[key]")
|
||||
CMD_( KEY_NONE, KEY_NONE, "global-set-key", do_global_set_key,
|
||||
"s{Set key globally: }s{command: }[command]|command|")
|
||||
"s{Set key globally: }[key]s{command: }[command]|command|")
|
||||
|
||||
/* window handling */
|
||||
CMD0( KEY_CTRLX('o'), KEY_NONE, "other-window", do_other_window)
|
||||
|
|
@ -106,7 +108,7 @@ CmdDef basic_commands[] = {
|
|||
/* help */
|
||||
CMD0( KEY_CTRLH(KEY_CTRL('h')), KEY_F1, "help-for-help", do_help_for_help)
|
||||
CMD0( KEY_CTRLH('b'), KEY_NONE, "describe-bindings", do_describe_bindings)
|
||||
CMD0( KEY_CTRLH('c'), KEY_NONE, "describe-key-briefly",
|
||||
CMD0( KEY_CTRLH('c'), KEY_CTRLH('k'), "describe-key-briefly",
|
||||
do_describe_key_briefly)
|
||||
|
||||
/* international */
|
||||
|
|
|
|||
66
shell.c
66
shell.c
|
|
@ -54,6 +54,7 @@ typedef struct ShellState {
|
|||
int esc_params[MAX_ESC_PARAMS];
|
||||
int nb_esc_params;
|
||||
int state;
|
||||
int shifted;
|
||||
EditBuffer *b;
|
||||
EditBuffer *b_color; /* color buffer, one byte per char */
|
||||
int is_shell; /* only used to display final message */
|
||||
|
|
@ -233,6 +234,7 @@ void tty_csi_m(ShellState *s, int c)
|
|||
/* Well, almost a hack to update cursor */
|
||||
static void tty_update_cursor(ShellState *s)
|
||||
{
|
||||
#if 0
|
||||
QEmacsState *qs = s->qe_state;
|
||||
EditState *e;
|
||||
|
||||
|
|
@ -244,6 +246,17 @@ static void tty_update_cursor(ShellState *s)
|
|||
e->offset = s->cur_offset;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* CG: much cleaner way! */
|
||||
/* would need a kill hook as well ? */
|
||||
static void shell_display_hook(EditState *e)
|
||||
{
|
||||
ShellState *s = e->b->priv_data;
|
||||
|
||||
if (e->interactive)
|
||||
e->offset = s->cur_offset;
|
||||
}
|
||||
|
||||
static void tty_emulate(ShellState *s, int c)
|
||||
|
|
@ -288,6 +301,14 @@ static void tty_emulate(ShellState *s, int c)
|
|||
s->cur_offset = offset1;
|
||||
}
|
||||
break;
|
||||
case 14:
|
||||
eb_set_charset(s->b, &charset_8859_1);
|
||||
s->shifted = 1;
|
||||
break;
|
||||
case 15:
|
||||
eb_set_charset(s->b, &charset_cp1125);
|
||||
s->shifted = 0;
|
||||
break;
|
||||
case 27:
|
||||
s->state = TTY_STATE_ESC;
|
||||
break;
|
||||
|
|
@ -317,7 +338,7 @@ static void tty_emulate(ShellState *s, int c)
|
|||
break;
|
||||
case TTY_STATE_ESC:
|
||||
if (c == '[') {
|
||||
for(i=0;i<MAX_ESC_PARAMS;i++)
|
||||
for (i = 0; i < MAX_ESC_PARAMS; i++)
|
||||
s->esc_params[i] = 0;
|
||||
s->nb_esc_params = 0;
|
||||
s->state = TTY_STATE_CSI;
|
||||
|
|
@ -663,36 +684,46 @@ void shell_move_left_right(EditState *e, int dir)
|
|||
{
|
||||
if (e->interactive) {
|
||||
ShellState *s = e->b->priv_data;
|
||||
if (dir > 0)
|
||||
tty_write(s, "\033[C", -1);
|
||||
else
|
||||
tty_write(s, "\033[D", -1);
|
||||
tty_write(s, dir > 0 ? "\033[C" : "\033[D", -1);
|
||||
} else {
|
||||
text_move_left_right_visual(e, dir);
|
||||
}
|
||||
}
|
||||
|
||||
void shell_move_word_left_right(EditState *e, int dir)
|
||||
{
|
||||
if (e->interactive) {
|
||||
ShellState *s = e->b->priv_data;
|
||||
tty_write(s, dir > 0 ? "\033f" : "\033b", -1);
|
||||
} else {
|
||||
text_move_word_left_right(e, dir);
|
||||
}
|
||||
}
|
||||
|
||||
void shell_move_up_down(EditState *e, int dir)
|
||||
{
|
||||
if (e->interactive) {
|
||||
ShellState *s = e->b->priv_data;
|
||||
|
||||
if (dir > 0)
|
||||
tty_write(s, "\033[B", -1);
|
||||
else
|
||||
tty_write(s, "\033[A", -1);
|
||||
tty_write(s, dir > 0 ? "\033[B" : "\033[A", -1);
|
||||
} else {
|
||||
text_move_up_down(e, dir);
|
||||
}
|
||||
}
|
||||
|
||||
void shell_scroll_up_down(EditState *e, int dir)
|
||||
{
|
||||
ShellState *s = e->b->priv_data;
|
||||
|
||||
e->interactive = 0;
|
||||
text_scroll_up_down(e, dir);
|
||||
e->interactive = (e->offset == s->cur_offset);
|
||||
}
|
||||
|
||||
void shell_move_bol(EditState *e)
|
||||
{
|
||||
if (e->interactive) {
|
||||
ShellState *s = e->b->priv_data;
|
||||
unsigned char ch;
|
||||
ch = 1;
|
||||
tty_write(s, &ch, 1);
|
||||
tty_write(s, "\001", -1); /* Control-A */
|
||||
} else {
|
||||
text_move_bol(e);
|
||||
}
|
||||
|
|
@ -702,9 +733,7 @@ void shell_move_eol(EditState *e)
|
|||
{
|
||||
if (e->interactive) {
|
||||
ShellState *s = e->b->priv_data;
|
||||
unsigned char ch;
|
||||
ch = 5;
|
||||
tty_write(s, &ch, 1);
|
||||
tty_write(s, "\005", -1); /* Control-E */
|
||||
} else {
|
||||
text_move_eol(e);
|
||||
}
|
||||
|
|
@ -746,10 +775,12 @@ void shell_write_char(EditState *e, int c)
|
|||
void do_shell_toggle_input(EditState *e)
|
||||
{
|
||||
e->interactive = !e->interactive;
|
||||
#if 0
|
||||
if (e->interactive) {
|
||||
ShellState *s = e->b->priv_data;
|
||||
tty_update_cursor(s);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static int error_offset = -1;
|
||||
|
|
@ -916,8 +947,11 @@ static int shell_init(void)
|
|||
shell_mode.name = "shell";
|
||||
shell_mode.mode_probe = NULL;
|
||||
shell_mode.mode_init = shell_mode_init;
|
||||
shell_mode.display_hook = shell_display_hook;
|
||||
shell_mode.move_left_right = shell_move_left_right;
|
||||
shell_mode.move_word_left_right = shell_move_word_left_right;
|
||||
shell_mode.move_up_down = shell_move_up_down;
|
||||
shell_mode.scroll_up_down = shell_scroll_up_down;
|
||||
shell_mode.move_bol = shell_move_bol;
|
||||
shell_mode.move_eol = shell_move_eol;
|
||||
shell_mode.write_char = shell_write_char;
|
||||
|
|
|
|||
156
tty.c
156
tty.c
|
|
@ -41,6 +41,7 @@ enum InputState {
|
|||
IS_NORM,
|
||||
IS_ESC,
|
||||
IS_CSI,
|
||||
IS_CSI2,
|
||||
IS_ESC2,
|
||||
};
|
||||
|
||||
|
|
@ -103,6 +104,7 @@ static int term_init(QEditScreen *s, int w, int h)
|
|||
s->charset = &charset_8859_1;
|
||||
|
||||
#ifndef CONFIG_CYGWIN
|
||||
/* CG: Should also have a command line switch */
|
||||
/* test UTF8 support by looking at the cursor position (idea from
|
||||
Ricardas Cepas <rch@pub.osf.lt>). Since uClibc actually tests
|
||||
to ensure that the format string is a valid multibyte sequence
|
||||
|
|
@ -197,6 +199,11 @@ static void tty_resize(int sig)
|
|||
s->clip_y2 = s->height;
|
||||
}
|
||||
|
||||
static void term_invalidate(void)
|
||||
{
|
||||
tty_resize(0);
|
||||
}
|
||||
|
||||
static void term_cursor_at(QEditScreen *s, int x1, int y1, int w, int h)
|
||||
{
|
||||
TTYState *ts = s->private;
|
||||
|
|
@ -219,6 +226,44 @@ static int term_is_user_input_pending(QEditScreen *s)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int const csi_lookup[] = {
|
||||
KEY_NONE, /* 0 */
|
||||
KEY_HOME, /* 1 */
|
||||
KEY_INSERT, /* 2 */
|
||||
KEY_DELETE, /* 3 */
|
||||
KEY_END, /* 4 */
|
||||
KEY_PAGEUP, /* 5 */
|
||||
KEY_PAGEDOWN, /* 6 */
|
||||
KEY_NONE, /* 7 */
|
||||
KEY_NONE, /* 8 */
|
||||
KEY_NONE, /* 9 */
|
||||
KEY_NONE, /* 10 */
|
||||
KEY_F1, /* 11 */
|
||||
KEY_F2, /* 12 */
|
||||
KEY_F3, /* 13 */
|
||||
KEY_F4, /* 14 */
|
||||
KEY_F5, /* 15 */
|
||||
KEY_NONE, /* 16 */
|
||||
KEY_F6, /* 17 */
|
||||
KEY_F7, /* 18 */
|
||||
KEY_F8, /* 19 */
|
||||
KEY_F9, /* 20 */
|
||||
KEY_F10, /* 21 */
|
||||
KEY_NONE, /* 22 */
|
||||
KEY_F11, /* 23 */
|
||||
KEY_F12, /* 24 */
|
||||
KEY_F13, /* 25 */
|
||||
KEY_F14, /* 26 */
|
||||
KEY_NONE, /* 27 */
|
||||
KEY_F15, /* 28 */
|
||||
KEY_F16, /* 29 */
|
||||
KEY_NONE, /* 30 */
|
||||
KEY_F17, /* 31 */
|
||||
KEY_F18, /* 32 */
|
||||
KEY_F19, /* 33 */
|
||||
KEY_F20, /* 34 */
|
||||
};
|
||||
|
||||
static void tty_read_handler(void *opaque)
|
||||
{
|
||||
QEditScreen *s = opaque;
|
||||
|
|
@ -232,6 +277,13 @@ static void tty_read_handler(void *opaque)
|
|||
if (trace_buffer) {
|
||||
eb_write(trace_buffer, trace_buffer->total_size,
|
||||
ts->buf + ts->utf8_index, 1);
|
||||
#if 0
|
||||
ch = ts->buf[ts->utf8_index];
|
||||
if (ch < 32 || ch == 127)
|
||||
fprintf(stderr, "got %d '^%c'\n", ch, ('@' + ch) & 127);
|
||||
else
|
||||
fprintf(stderr, "got %d '%c'\n", ch, ch);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* charset handling */
|
||||
|
|
@ -257,6 +309,10 @@ static void tty_read_handler(void *opaque)
|
|||
goto the_end;
|
||||
break;
|
||||
case IS_ESC:
|
||||
if (ch == '\033') {
|
||||
/* cygwin A-right transmit ESC ESC[C ... */
|
||||
goto the_end;
|
||||
}
|
||||
if (ch == '[') {
|
||||
ts->input_state = IS_CSI;
|
||||
ts->input_param = 0;
|
||||
|
|
@ -269,43 +325,82 @@ static void tty_read_handler(void *opaque)
|
|||
}
|
||||
break;
|
||||
case IS_CSI:
|
||||
if (!isdigit(ch)) {
|
||||
ts->input_state = IS_NORM;
|
||||
switch(ch) {
|
||||
case '~':
|
||||
ch = KEY_ESC1(ts->input_param);
|
||||
goto the_end;
|
||||
case 'H':
|
||||
ch = KEY_HOME;
|
||||
goto the_end;
|
||||
case 'F':
|
||||
ch = KEY_END;
|
||||
goto the_end;
|
||||
case 'Z':
|
||||
ch = KEY_SHIFT_TAB;
|
||||
goto the_end;
|
||||
default:
|
||||
/* xterm CTRL-arrows */
|
||||
if (ts->input_param == 5 && ch >= 'A' && ch <= 'D')
|
||||
ch += 'a' - 'A';
|
||||
ch = KEY_ESC1(ch);
|
||||
if (isdigit(ch)) {
|
||||
ts->input_param = ts->input_param * 10 + ch - '0';
|
||||
break;
|
||||
}
|
||||
ts->input_state = IS_NORM;
|
||||
switch(ch) {
|
||||
case '[':
|
||||
ts->input_state = IS_CSI2;
|
||||
break;
|
||||
case '~':
|
||||
if (ts->input_param < sizeof(csi_lookup)/sizeof(csi_lookup[0])) {
|
||||
ch = csi_lookup[ts->input_param];
|
||||
goto the_end;
|
||||
}
|
||||
} else {
|
||||
ts->input_param = ts->input_param * 10 + ch - '0';
|
||||
break;
|
||||
/* All these for ansi|cygwin */
|
||||
case 'A': ch = KEY_UP; goto the_end; // kcuu1
|
||||
case 'B': ch = KEY_DOWN; goto the_end; // kcud1
|
||||
case 'C': ch = KEY_RIGHT; goto the_end; // kcuf1
|
||||
case 'D': ch = KEY_LEFT; goto the_end; // kcub1
|
||||
case 'F': ch = KEY_END; goto the_end; // kend
|
||||
//case 'G': ch = KEY_CENTER; goto the_end; // kb2
|
||||
case 'H': ch = KEY_HOME; goto the_end; // khome
|
||||
case 'L': ch = KEY_INSERT; goto the_end; // kich1
|
||||
//case 'M': ch = KEY_MOUSE; goto the_end; // kmous
|
||||
case 'Z': ch = KEY_SHIFT_TAB; goto the_end; // kcbt
|
||||
default:
|
||||
#if 0 /* xterm CTRL-arrows */
|
||||
if (ts->input_param == 5) {
|
||||
switch (ch) {
|
||||
case 'A': ch = KEY_CTRL_UP; goto the_end;
|
||||
case 'B': ch = KEY_CTRL_DOWN; goto the_end;
|
||||
case 'C': ch = KEY_CTRL_RIGHT; goto the_end;
|
||||
case 'D': ch = KEY_CTRL_LEFT; goto the_end;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case IS_ESC2:
|
||||
/* xterm fn */
|
||||
case IS_CSI2:
|
||||
/* cygwin/linux terminal */
|
||||
ts->input_state = IS_NORM;
|
||||
if (ch >= 'P' && ch <= 'S') {
|
||||
ch = KEY_F1 + ch - 'P';
|
||||
the_end:
|
||||
ev->key_event.type = QE_KEY_EVENT;
|
||||
ev->key_event.key = ch;
|
||||
qe_handle_event(ev);
|
||||
switch(ch) {
|
||||
case 'A': ch = KEY_F1; goto the_end;
|
||||
case 'B': ch = KEY_F2; goto the_end;
|
||||
case 'C': ch = KEY_F3; goto the_end;
|
||||
case 'D': ch = KEY_F4; goto the_end;
|
||||
case 'E': ch = KEY_F5; goto the_end;
|
||||
}
|
||||
break;
|
||||
case IS_ESC2: // "\EO"
|
||||
/* xterm/vt100 fn */
|
||||
ts->input_state = IS_NORM;
|
||||
switch(ch) {
|
||||
case 'A': ch = KEY_UP; goto the_end;
|
||||
case 'B': ch = KEY_DOWN; goto the_end;
|
||||
case 'C': ch = KEY_RIGHT; goto the_end;
|
||||
case 'D': ch = KEY_LEFT; goto the_end;
|
||||
case 'P': ch = KEY_F1; goto the_end;
|
||||
case 'Q': ch = KEY_F2; goto the_end;
|
||||
case 'R': ch = KEY_F3; goto the_end;
|
||||
case 'S': ch = KEY_F4; goto the_end;
|
||||
case 't': ch = KEY_F5; goto the_end;
|
||||
case 'u': ch = KEY_F6; goto the_end;
|
||||
case 'v': ch = KEY_F7; goto the_end;
|
||||
case 'l': ch = KEY_F8; goto the_end;
|
||||
case 'w': ch = KEY_F9; goto the_end;
|
||||
case 'x': ch = KEY_F10; goto the_end;
|
||||
}
|
||||
break;
|
||||
the_end:
|
||||
ev->key_event.type = QE_KEY_EVENT;
|
||||
ev->key_event.key = ch;
|
||||
qe_handle_event(ev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -577,6 +672,7 @@ static QEDisplay tty_dpy = {
|
|||
term_set_clip,
|
||||
NULL, /* no selection handling */
|
||||
NULL, /* no selection handling */
|
||||
term_invalidate,
|
||||
};
|
||||
|
||||
static int tty_init(void)
|
||||
|
|
|
|||
183
util.c
183
util.c
|
|
@ -466,64 +466,95 @@ int css_get_enum(const char *str, const char *enum_str)
|
|||
}
|
||||
|
||||
unsigned short keycodes[] = {
|
||||
KEY_LEFT,
|
||||
KEY_RIGHT,
|
||||
KEY_UP,
|
||||
KEY_DOWN,
|
||||
KEY_CTRL_LEFT,
|
||||
KEY_CTRL_RIGHT,
|
||||
KEY_CTRL_UP,
|
||||
KEY_CTRL_DOWN,
|
||||
KEY_CTRL_HOME,
|
||||
KEY_CTRL_END,
|
||||
KEY_CTRL(' '),
|
||||
KEY_CTRL('\\'),
|
||||
KEY_CTRL(']'),
|
||||
KEY_CTRL('^'),
|
||||
KEY_CTRL('_'),
|
||||
KEY_BACKSPACE,
|
||||
KEY_INSERT,
|
||||
KEY_DELETE,
|
||||
KEY_PAGEUP,
|
||||
KEY_PAGEDOWN,
|
||||
KEY_HOME,
|
||||
KEY_END,
|
||||
' ',
|
||||
KEY_RET,
|
||||
KEY_ESC,
|
||||
KEY_TAB,
|
||||
KEY_SHIFT_TAB,
|
||||
KEY_DEFAULT,
|
||||
KEY_SPC, KEY_DEL, KEY_RET, KEY_ESC, KEY_TAB, KEY_SHIFT_TAB,
|
||||
KEY_CTRL(' '), KEY_DEL, KEY_CTRL('\\'),
|
||||
KEY_CTRL(']'), KEY_CTRL('^'), KEY_CTRL('_'),
|
||||
KEY_LEFT, KEY_RIGHT, KEY_UP, KEY_DOWN,
|
||||
KEY_HOME, KEY_END, KEY_PAGEUP, KEY_PAGEDOWN,
|
||||
KEY_CTRL_LEFT, KEY_CTRL_RIGHT, KEY_CTRL_UP, KEY_CTRL_DOWN,
|
||||
KEY_CTRL_HOME, KEY_CTRL_END, KEY_CTRL_PAGEUP, KEY_CTRL_PAGEDOWN,
|
||||
KEY_PAGEUP, KEY_PAGEDOWN, KEY_CTRL_PAGEUP, KEY_CTRL_PAGEDOWN,
|
||||
KEY_INSERT, KEY_DELETE, KEY_DEFAULT,
|
||||
KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5,
|
||||
KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10,
|
||||
KEY_F11, KEY_F12, KEY_F13, KEY_F14, KEY_F15,
|
||||
KEY_F16, KEY_F17, KEY_F18, KEY_F19, KEY_F20,
|
||||
};
|
||||
|
||||
const char *keystr[] = {
|
||||
"SPC", "DEL", "RET", "ESC", "TAB", "S-TAB",
|
||||
"C-SPC", "C-?", "C-\\", "C-]", "C-^", "C-_",
|
||||
"left", "right", "up", "down",
|
||||
"C-left", "C-right", "C-up", "C-down",
|
||||
"C-home", "C-end",
|
||||
"C-space", "C-\\", "C-]", "C-^", "C-_",
|
||||
"backspace", "insert", "delete", "prior", "next",
|
||||
"home", "end",
|
||||
"SPC", "RET", "ESC",
|
||||
"TAB", "S-TAB",
|
||||
"default",
|
||||
"home", "end", "prior", "next",
|
||||
"C-left", "C-right", "C-up", "C-down",
|
||||
"C-home", "C-end", "C-prior", "C-next",
|
||||
"pageup", "pagedown", "C-pageup", "C-pagedown",
|
||||
"insert", "delete", "default",
|
||||
"f1", "f2", "f3", "f4", "f5",
|
||||
"f6", "f7", "f8", "f9", "f10",
|
||||
"f11", "f12", "f13", "f14", "f15",
|
||||
"f16", "f17", "f18", "f19", "f20",
|
||||
};
|
||||
|
||||
static int strtokey1(const char *p)
|
||||
int compose_keys(int *keys, int *nb_keys)
|
||||
{
|
||||
int i, n;
|
||||
int *keyp;
|
||||
|
||||
for (i = 0; i < (int)(sizeof(keycodes)/sizeof(keycodes[0])); i++) {
|
||||
if (!strcmp(p, keystr[i]))
|
||||
return keycodes[i];
|
||||
if (*nb_keys < 2)
|
||||
return 0;
|
||||
|
||||
/* compose KEY_ESC as META prefix */
|
||||
keyp = keys + *nb_keys - 2;
|
||||
if (keyp[0] == KEY_ESC) {
|
||||
if (keyp[1] <= 0xff) {
|
||||
keyp[0] = KEY_META(keyp[1]);
|
||||
--*nb_keys;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* CG: this code is still quite inelegant */
|
||||
static int strtokey1(const char **pp)
|
||||
{
|
||||
const char *p, *p1, *q;
|
||||
int i, key;
|
||||
|
||||
/* should return KEY_NONE at end and KEY_UNKNOWN if unrecognized */
|
||||
p = *pp;
|
||||
|
||||
/* scan for separator */
|
||||
for (p1 = p; *p1 && *p1 != ' '; p1++)
|
||||
continue;
|
||||
|
||||
for (i = 0; i < sizeof(keycodes)/sizeof(keycodes[0]); i++) {
|
||||
if (strstart(p, keystr[i], &q) && q == p1) {
|
||||
key = keycodes[i];
|
||||
*pp = p1;
|
||||
return key;
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
if (p[0] == 'f' && p[1] >= '1' && p[1] <= '9') {
|
||||
p++;
|
||||
n = *p - '0';
|
||||
if (isdigit((unsigned char)p[1]))
|
||||
n = n * 10 + p[1] - '0';
|
||||
return KEY_F1 + n - 1;
|
||||
i = p[1] - '0';
|
||||
p += 2;
|
||||
if (p1 == isdigit((unsigned char)*p))
|
||||
i = i * 10 + *p++ - '0';
|
||||
key = KEY_F1 + i - 1;
|
||||
*pp = p1;
|
||||
return key;
|
||||
}
|
||||
return utf8_decode(&p);
|
||||
#endif
|
||||
if (p[0] == 'C' && p[1] == '-' && p1 == p + 3) {
|
||||
/* control */
|
||||
key = KEY_CTRL(p[2]);
|
||||
} else {
|
||||
key = utf8_decode(&p);
|
||||
}
|
||||
*pp = p1;
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
int strtokey(const char **pp)
|
||||
|
|
@ -531,29 +562,42 @@ int strtokey(const char **pp)
|
|||
const char *p;
|
||||
int key;
|
||||
|
||||
/* XXX: handle all cases */
|
||||
p = *pp;
|
||||
if (p[0] == 'C' && p[1] == '-') {
|
||||
/* control */
|
||||
if (p[0] == 'M' && p[1] == '-') {
|
||||
p += 2;
|
||||
key = strtokey1(p);
|
||||
if (key >= 'a' && key <= 'z')
|
||||
key = KEY_CTRL(key);
|
||||
} else if (p[0] == 'M' && p[1] == '-') {
|
||||
p += 2;
|
||||
key = strtokey1(p);
|
||||
if ((key >= 'a' && key <= 'z') ||
|
||||
key == KEY_BACKSPACE)
|
||||
key = KEY_META(key);
|
||||
key = KEY_META(strtokey1(&p));
|
||||
} else
|
||||
if (p[0] == 'C' && p[1] == '-' && p[0] == 'M' && p[1] == '-') {
|
||||
p += 4;
|
||||
key = KEY_META(KEY_CTRL(strtokey1(&p)));
|
||||
} else {
|
||||
key = strtokey1(p);
|
||||
key = strtokey1(&p);
|
||||
}
|
||||
while (*p != ' ' && *p != '\0')
|
||||
p++;
|
||||
*pp = p;
|
||||
return key;
|
||||
}
|
||||
|
||||
int strtokeys(const char *keystr, unsigned int *keys, int max_keys)
|
||||
{
|
||||
int key, nb_keys;
|
||||
const char *p;
|
||||
|
||||
p = keystr;
|
||||
nb_keys = 0;
|
||||
|
||||
for (;;) {
|
||||
skip_spaces(&p);
|
||||
if (*p == '\0')
|
||||
break;
|
||||
key = strtokey(&p);
|
||||
keys[nb_keys++] = key;
|
||||
compose_keys(keys, &nb_keys);
|
||||
if (nb_keys >= max_keys)
|
||||
break;
|
||||
}
|
||||
return nb_keys;
|
||||
}
|
||||
|
||||
void keytostr(char *buf, int buf_size, int key)
|
||||
{
|
||||
int i;
|
||||
|
|
@ -565,18 +609,21 @@ void keytostr(char *buf, int buf_size, int key)
|
|||
return;
|
||||
}
|
||||
}
|
||||
if (key >= KEY_META(' ') && key <= KEY_META(127)) {
|
||||
if (key >= KEY_META(0) && key <= KEY_META(0xff)) {
|
||||
keytostr(buf1, sizeof(buf1), key & 0xff);
|
||||
snprintf(buf, buf_size, "M-%s", buf1);
|
||||
} else if (key >= 1 && key <= 31) {
|
||||
} else if (key >= KEY_CTRL('a') && key <= KEY_CTRL('z')) {
|
||||
snprintf(buf, buf_size, "C-%c", key + 'a' - 1);
|
||||
} else if (key >= KEY_F1 && key <= KEY_F12) {
|
||||
snprintf(buf, buf_size, "F%d", key - KEY_F1 + 1);
|
||||
} else if (key >= KEY_F1 && key <= KEY_F20) {
|
||||
snprintf(buf, buf_size, "f%d", key - KEY_F1 + 1);
|
||||
} else if (key > 32 && key < 127 && buf_size >= 2) {
|
||||
buf[0] = key;
|
||||
buf[1] = '\0';
|
||||
} else {
|
||||
char *q;
|
||||
/* CG: assuming buf_size > 5 */
|
||||
q = utf8_encode(buf, key);
|
||||
q = utf8_encode(buf1, key);
|
||||
*q = '\0';
|
||||
pstrcpy(buf, buf_size, buf1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
2
win32.c
2
win32.c
|
|
@ -268,7 +268,7 @@ LRESULT CALLBACK qe_wnd_proc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|||
switch(scan) {
|
||||
case 0x00E:
|
||||
ignore_wchar_msg = 1;
|
||||
push_key(KEY_BACKSPACE);
|
||||
push_key(KEY_DEL);
|
||||
break;
|
||||
case 0x039: /* space */
|
||||
ignore_wchar_msg = 1;
|
||||
|
|
|
|||
5
x11.c
5
x11.c
|
|
@ -1285,7 +1285,7 @@ static void x11_handle_event(void *opaque)
|
|||
} else if (meta) {
|
||||
switch(keysym) {
|
||||
case XK_BackSpace:
|
||||
key = KEY_META(KEY_BACKSPACE);
|
||||
key = KEY_META(KEY_DEL);
|
||||
goto got_key;
|
||||
default:
|
||||
if (keysym >= ' ' && keysym <= '~') {
|
||||
|
|
@ -1323,7 +1323,7 @@ static void x11_handle_event(void *opaque)
|
|||
key = KEY_LEFT;
|
||||
goto got_key;
|
||||
case XK_BackSpace:
|
||||
key = KEY_BACKSPACE;
|
||||
key = KEY_DEL;
|
||||
goto got_key;
|
||||
case XK_Insert:
|
||||
key = KEY_INSERT;
|
||||
|
|
@ -1676,6 +1676,7 @@ static QEDisplay x11_dpy = {
|
|||
term_set_clip,
|
||||
term_selection_activate,
|
||||
term_selection_request,
|
||||
NULL,
|
||||
x11_bmp_alloc,
|
||||
x11_bmp_free,
|
||||
x11_bmp_draw,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue