1998-02-27 07:54:42 +03:00
|
|
|
/* Keyboard support routines.
|
|
|
|
|
|
|
|
Copyright (C) 1994,1995 the Free Software Foundation.
|
|
|
|
|
|
|
|
Written by: 1994, 1995 Miguel de Icaza.
|
|
|
|
1994, 1995 Janne Kukonlehto.
|
|
|
|
1995 Jakub Jelinek.
|
|
|
|
1997 Norbert Warmuth
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
2000-08-23 02:50:00 +04:00
|
|
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
1998-02-27 07:54:42 +03:00
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <string.h>
|
|
|
|
#ifdef HAVE_UNISTD_H
|
|
|
|
# include <unistd.h>
|
|
|
|
#endif
|
1998-12-02 09:51:40 +03:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/time.h>
|
1998-02-27 07:54:42 +03:00
|
|
|
#if HAVE_SYS_SELECT_H
|
|
|
|
# include <sys/select.h>
|
|
|
|
#endif
|
|
|
|
#include "tty.h"
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include "global.h"
|
|
|
|
#include "mouse.h"
|
|
|
|
#include "key.h"
|
|
|
|
#include "main.h"
|
1998-04-01 02:36:24 +04:00
|
|
|
#include "win.h"
|
|
|
|
#include "cons.saver.h"
|
1998-02-27 07:54:42 +03:00
|
|
|
#include "../vfs/vfs.h"
|
|
|
|
|
2001-06-05 20:41:44 +04:00
|
|
|
#ifdef HAVE_TEXTMODE_X11_SUPPORT
|
1999-04-21 23:18:31 +04:00
|
|
|
#include <X11/Xlib.h>
|
|
|
|
#endif
|
|
|
|
|
1998-02-27 07:54:42 +03:00
|
|
|
#ifdef __linux__
|
|
|
|
# if defined(__GLIBC__) && (__GLIBC__ < 2)
|
|
|
|
# include <linux/termios.h> /* This is needed for TIOCLINUX */
|
|
|
|
# else
|
|
|
|
# include <termios.h>
|
|
|
|
# endif
|
|
|
|
# include <sys/ioctl.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "x.h"
|
|
|
|
|
1998-12-02 09:51:40 +03:00
|
|
|
#define GET_TIME(tv) (gettimeofday(&tv, (struct timezone *)NULL))
|
1998-02-27 07:54:42 +03:00
|
|
|
#define DIF_TIME(t1,t2) ((t2.tv_sec -t1.tv_sec) *1000+ \
|
|
|
|
(t2.tv_usec-t1.tv_usec)/1000)
|
|
|
|
|
|
|
|
/* timeout for old_esc_mode in usec */
|
|
|
|
#define ESCMODE_TIMEOUT 1000000
|
|
|
|
|
|
|
|
int mou_auto_repeat = 100;
|
|
|
|
int double_click_speed = 250;
|
|
|
|
int old_esc_mode = 0;
|
|
|
|
|
|
|
|
int use_8th_bit_as_meta = 1;
|
|
|
|
|
|
|
|
typedef struct key_def {
|
|
|
|
char ch; /* Holds the matching char code */
|
|
|
|
int code; /* The code returned, valid if child == NULL */
|
|
|
|
struct key_def *next;
|
|
|
|
struct key_def *child; /* sequence continuation */
|
|
|
|
int action; /* optional action to be done. Now used only
|
|
|
|
to mark that we are just after the first
|
|
|
|
Escape */
|
|
|
|
} key_def;
|
|
|
|
|
|
|
|
/* This holds all the key definitions */
|
|
|
|
static key_def *keys = 0;
|
|
|
|
|
|
|
|
static int input_fd;
|
|
|
|
static fd_set select_set;
|
|
|
|
static int disabled_channels = 0; /* Disable channels checking */
|
2001-07-20 20:19:28 +04:00
|
|
|
static int xgetch_second (void);
|
1998-02-27 07:54:42 +03:00
|
|
|
|
|
|
|
/* File descriptor monitoring add/remove routines */
|
|
|
|
typedef struct SelectList {
|
|
|
|
int fd;
|
|
|
|
select_fn callback;
|
|
|
|
void *info;
|
|
|
|
struct SelectList *next;
|
|
|
|
} SelectList;
|
|
|
|
|
2001-06-05 20:41:44 +04:00
|
|
|
static SelectList *select_list = 0;
|
1998-02-27 07:54:42 +03:00
|
|
|
|
|
|
|
void add_select_channel (int fd, select_fn callback, void *info)
|
|
|
|
{
|
|
|
|
SelectList *new;
|
|
|
|
|
Glibing..... (2)
Wed Jan 27 03:17:44 1999 Timur Bakeyev <mc@bat.ru>
* Converted memory managment to Glib. Now we use g_new()/g_malloc()/
g_strdup()/g_free() routings. Also, copy_strings() replaced by
g_strconcat(), strcasecmp() -> g_strcasecmp(),and sprintf() by
g_snprintf().
* Some sequences of malloc()/sprintf() changed to g_strdup_printf().
* mad.[ch]: Modified, to work with new GLib's memory managment. Fixed
a missing #undef for tempnam, which caused dead loop. Add several new
functions to emulate GLib memory managment.
*main.c, mad.[ch]: Add a new switch "-M", which allows to redirect MAD
messages to the file.
* util.[ch], utilunix.c: Modified, deleted our variants of strcasecmp()
and strdup() - we have g_ equivalences. Remove get_full_name() - it is
similar to concat_dir_and_file(). Some other tricks with g_* functions.
* global.h: Modified, extended. Now it is main memory mangment include -
i.e. all inclusions of <stdlib.h>, <malloc.h>, <glib.h>, "fs.h", "mem.h",
"util.h" and "mad.h" done there. This elimanates problem with proper or-
der of #include's.
* All around the source - changed order of #include's, most of them gone
to global.h (see above), minor changes, like "0" -> NULL in string func-
tions.
1999-01-27 04:08:30 +03:00
|
|
|
new = g_new (SelectList, 1);
|
1998-02-27 07:54:42 +03:00
|
|
|
new->fd = fd;
|
|
|
|
new->callback = callback;
|
|
|
|
new->info = info;
|
|
|
|
new->next = select_list;
|
|
|
|
select_list = new;
|
|
|
|
}
|
|
|
|
|
|
|
|
void delete_select_channel (int fd)
|
|
|
|
{
|
|
|
|
SelectList *p = select_list;
|
|
|
|
SelectList *prev = 0;
|
|
|
|
|
|
|
|
while (p){
|
|
|
|
if (p->fd == fd){
|
|
|
|
if (prev)
|
|
|
|
prev->next = p->next;
|
|
|
|
else
|
|
|
|
select_list = p->next;
|
Glibing..... (2)
Wed Jan 27 03:17:44 1999 Timur Bakeyev <mc@bat.ru>
* Converted memory managment to Glib. Now we use g_new()/g_malloc()/
g_strdup()/g_free() routings. Also, copy_strings() replaced by
g_strconcat(), strcasecmp() -> g_strcasecmp(),and sprintf() by
g_snprintf().
* Some sequences of malloc()/sprintf() changed to g_strdup_printf().
* mad.[ch]: Modified, to work with new GLib's memory managment. Fixed
a missing #undef for tempnam, which caused dead loop. Add several new
functions to emulate GLib memory managment.
*main.c, mad.[ch]: Add a new switch "-M", which allows to redirect MAD
messages to the file.
* util.[ch], utilunix.c: Modified, deleted our variants of strcasecmp()
and strdup() - we have g_ equivalences. Remove get_full_name() - it is
similar to concat_dir_and_file(). Some other tricks with g_* functions.
* global.h: Modified, extended. Now it is main memory mangment include -
i.e. all inclusions of <stdlib.h>, <malloc.h>, <glib.h>, "fs.h", "mem.h",
"util.h" and "mad.h" done there. This elimanates problem with proper or-
der of #include's.
* All around the source - changed order of #include's, most of them gone
to global.h (see above), minor changes, like "0" -> NULL in string func-
tions.
1999-01-27 04:08:30 +03:00
|
|
|
g_free (p);
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
prev = p;
|
|
|
|
p = p->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
inline static int add_selects (fd_set *select_set)
|
|
|
|
{
|
|
|
|
SelectList *p;
|
|
|
|
int top_fd = 0;
|
|
|
|
|
|
|
|
if (disabled_channels)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
for (p = select_list; p; p = p->next){
|
|
|
|
FD_SET (p->fd, select_set);
|
|
|
|
if (p->fd > top_fd)
|
|
|
|
top_fd = p->fd;
|
|
|
|
}
|
|
|
|
return top_fd;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void check_selects (fd_set *select_set)
|
|
|
|
{
|
|
|
|
SelectList *p;
|
|
|
|
|
|
|
|
if (disabled_channels)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (p = select_list; p; p = p->next)
|
|
|
|
if (FD_ISSET (p->fd, select_set))
|
|
|
|
(*p->callback)(p->fd, p->info);
|
|
|
|
}
|
|
|
|
|
|
|
|
void channels_down (void)
|
|
|
|
{
|
|
|
|
disabled_channels ++;
|
|
|
|
}
|
|
|
|
|
|
|
|
void channels_up (void)
|
|
|
|
{
|
|
|
|
if (!disabled_channels)
|
|
|
|
fprintf (stderr,
|
|
|
|
"Error: channels_up called with disabled_channels = 0\n");
|
|
|
|
disabled_channels--;
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
int code;
|
|
|
|
char *seq;
|
|
|
|
int action;
|
|
|
|
} key_define_t;
|
|
|
|
|
2001-06-05 20:41:44 +04:00
|
|
|
static key_define_t mc_bindings [] = {
|
1998-02-27 07:54:42 +03:00
|
|
|
{ KEY_END, ESC_STR ">", MCKEY_NOACTION },
|
|
|
|
{ KEY_HOME, ESC_STR "<", MCKEY_NOACTION },
|
|
|
|
{ 0, 0, MCKEY_NOACTION },
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Broken terminfo and termcap databases on xterminals */
|
2001-06-05 20:41:44 +04:00
|
|
|
static key_define_t xterm_key_defines [] = {
|
1998-02-27 07:54:42 +03:00
|
|
|
{ KEY_F(1), ESC_STR "OP", MCKEY_NOACTION },
|
|
|
|
{ KEY_F(2), ESC_STR "OQ", MCKEY_NOACTION },
|
|
|
|
{ KEY_F(3), ESC_STR "OR", MCKEY_NOACTION },
|
|
|
|
{ KEY_F(4), ESC_STR "OS", MCKEY_NOACTION },
|
|
|
|
{ KEY_F(1), ESC_STR "[11~", MCKEY_NOACTION },
|
|
|
|
{ KEY_F(2), ESC_STR "[12~", MCKEY_NOACTION },
|
|
|
|
{ KEY_F(3), ESC_STR "[13~", MCKEY_NOACTION },
|
|
|
|
{ KEY_F(4), ESC_STR "[14~", MCKEY_NOACTION },
|
|
|
|
{ KEY_F(5), ESC_STR "[15~", MCKEY_NOACTION },
|
|
|
|
{ KEY_F(6), ESC_STR "[17~", MCKEY_NOACTION },
|
|
|
|
{ KEY_F(7), ESC_STR "[18~", MCKEY_NOACTION },
|
|
|
|
{ KEY_F(8), ESC_STR "[19~", MCKEY_NOACTION },
|
|
|
|
{ KEY_F(9), ESC_STR "[20~", MCKEY_NOACTION },
|
|
|
|
{ KEY_F(10), ESC_STR "[21~", MCKEY_NOACTION },
|
|
|
|
{ 0, 0, MCKEY_NOACTION },
|
|
|
|
};
|
|
|
|
|
2001-06-05 20:41:44 +04:00
|
|
|
static key_define_t mc_default_keys [] = {
|
1998-02-27 07:54:42 +03:00
|
|
|
{ ESC_CHAR, ESC_STR, MCKEY_ESCAPE },
|
|
|
|
{ ESC_CHAR, ESC_STR ESC_STR, MCKEY_NOACTION },
|
|
|
|
{ 0, 0, MCKEY_NOACTION },
|
|
|
|
};
|
|
|
|
|
1998-12-03 00:27:27 +03:00
|
|
|
static void
|
|
|
|
define_sequences (key_define_t *kd)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; kd [i].code; i++)
|
|
|
|
define_sequence(kd [i].code, kd [i].seq, kd [i].action);
|
|
|
|
}
|
|
|
|
|
2001-06-05 20:41:44 +04:00
|
|
|
#ifdef HAVE_TEXTMODE_X11_SUPPORT
|
2001-06-06 02:08:31 +04:00
|
|
|
static Display *x11_display;
|
|
|
|
static Window x11_window;
|
|
|
|
#endif /* HAVE_TEXTMODE_X11_SUPPORT */
|
1999-04-21 23:18:31 +04:00
|
|
|
|
1998-02-27 07:54:42 +03:00
|
|
|
/* This has to be called before slang_init or whatever routine
|
|
|
|
calls any define_sequence */
|
|
|
|
void init_key (void)
|
|
|
|
{
|
|
|
|
char *term = (char *) getenv ("TERM");
|
|
|
|
|
|
|
|
/* This has to be the first define_sequence */
|
|
|
|
/* So, we can assume that the first keys member has ESC */
|
|
|
|
define_sequences (mc_default_keys);
|
|
|
|
|
|
|
|
/* Terminfo on irix does not have some keys */
|
|
|
|
if ((!strncmp (term, "iris-ansi", 9)) || (!strncmp (term, "xterm", 5)))
|
|
|
|
define_sequences (xterm_key_defines);
|
|
|
|
|
|
|
|
define_sequences (mc_bindings);
|
1998-05-20 06:19:17 +04:00
|
|
|
|
|
|
|
/* load some additional keys (e.g. direct Alt-? support) */
|
|
|
|
load_xtra_key_defines();
|
|
|
|
|
|
|
|
#ifdef __QNX__
|
|
|
|
if (strncmp(term, "qnx", 3) == 0){
|
|
|
|
/* Modify the default value of use_8th_bit_as_meta: we would
|
|
|
|
* like to provide a working mc for a newbie who knows nothing
|
|
|
|
* about [Options|Display bits|Full 8 bits input]...
|
|
|
|
*
|
|
|
|
* Don't use 'meta'-bit, when we are dealing with a
|
|
|
|
* 'qnx*'-type terminal: clear the default value!
|
|
|
|
* These terminal types use 0xFF as an escape character,
|
|
|
|
* so use_8th_bit_as_meta==1 must not be enabled!
|
|
|
|
*
|
|
|
|
* [mc-4.1.21+,slint.c/getch(): the DEC_8BIT_HACK stuff
|
|
|
|
* is not used now (doesn't even depend on use_8th_bit_as_meta
|
|
|
|
* as in mc-3.1.2)...GREAT!...no additional code is required!]
|
|
|
|
*/
|
|
|
|
use_8th_bit_as_meta = 0;
|
|
|
|
}
|
|
|
|
#endif /* __QNX__ */
|
2001-06-06 02:08:31 +04:00
|
|
|
|
|
|
|
#ifdef HAVE_TEXTMODE_X11_SUPPORT
|
|
|
|
x11_display = XOpenDisplay (0);
|
|
|
|
if (x11_display)
|
|
|
|
x11_window = DefaultRootWindow (x11_display);
|
|
|
|
#endif /* HAVE_TEXTMODE_X11_SUPPORT */
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* This has to be called after SLang_init_tty/slint_init */
|
|
|
|
void init_key_input_fd (void)
|
|
|
|
{
|
|
|
|
#ifdef HAVE_SLANG
|
|
|
|
input_fd = SLang_TT_Read_FD;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1998-12-03 00:27:27 +03:00
|
|
|
static void
|
|
|
|
xmouse_get_event (Gpm_Event *ev)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
|
|
|
int btn;
|
|
|
|
static struct timeval tv1 = { 0, 0 }; /* Force first click as single */
|
|
|
|
static struct timeval tv2;
|
|
|
|
static int clicks;
|
2001-08-18 23:27:31 +04:00
|
|
|
static int last_btn = 0;
|
1998-02-27 07:54:42 +03:00
|
|
|
|
|
|
|
/* Decode Xterm mouse information to a GPM style event */
|
|
|
|
|
|
|
|
/* Variable btn has following meaning: */
|
|
|
|
/* 0 = btn1 dn, 1 = btn2 dn, 2 = btn3 dn, 3 = btn up */
|
|
|
|
btn = xgetch () - 32;
|
|
|
|
|
|
|
|
/* There seems to be no way of knowing which button was released */
|
|
|
|
/* So we assume all the buttons were released */
|
|
|
|
|
|
|
|
if (btn == 3){
|
2001-08-18 23:27:31 +04:00
|
|
|
if (last_btn) {
|
|
|
|
ev->type = GPM_UP | (GPM_SINGLE << clicks);
|
|
|
|
ev->buttons = 0;
|
|
|
|
last_btn = 0;
|
|
|
|
GET_TIME (tv1);
|
|
|
|
clicks = 0;
|
|
|
|
} else {
|
|
|
|
/* Bogus event, maybe mouse wheel */
|
|
|
|
ev->type = 0;
|
|
|
|
}
|
1998-02-27 07:54:42 +03:00
|
|
|
} else {
|
|
|
|
ev->type = GPM_DOWN;
|
|
|
|
GET_TIME (tv2);
|
|
|
|
if (tv1.tv_sec && (DIF_TIME (tv1,tv2) < double_click_speed)){
|
|
|
|
clicks++;
|
|
|
|
clicks %= 3;
|
|
|
|
} else
|
|
|
|
clicks = 0;
|
|
|
|
|
|
|
|
switch (btn) {
|
|
|
|
case 0:
|
|
|
|
ev->buttons = GPM_B_LEFT;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
ev->buttons = GPM_B_MIDDLE;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
ev->buttons = GPM_B_RIGHT;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* Nothing */
|
2001-08-18 23:27:31 +04:00
|
|
|
ev->type = 0;
|
|
|
|
ev->buttons = 0;
|
1998-02-27 07:54:42 +03:00
|
|
|
break;
|
|
|
|
}
|
2001-08-18 23:27:31 +04:00
|
|
|
last_btn = ev->buttons;
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
/* Coordinates are 33-based */
|
|
|
|
/* Transform them to 1-based */
|
|
|
|
ev->x = xgetch () - 32;
|
|
|
|
ev->y = xgetch () - 32;
|
|
|
|
}
|
|
|
|
|
|
|
|
static key_def *create_sequence (char *seq, int code, int action)
|
|
|
|
{
|
|
|
|
key_def *base, *p, *attach;
|
|
|
|
|
|
|
|
for (base = attach = NULL; *seq; seq++){
|
Glibing..... (2)
Wed Jan 27 03:17:44 1999 Timur Bakeyev <mc@bat.ru>
* Converted memory managment to Glib. Now we use g_new()/g_malloc()/
g_strdup()/g_free() routings. Also, copy_strings() replaced by
g_strconcat(), strcasecmp() -> g_strcasecmp(),and sprintf() by
g_snprintf().
* Some sequences of malloc()/sprintf() changed to g_strdup_printf().
* mad.[ch]: Modified, to work with new GLib's memory managment. Fixed
a missing #undef for tempnam, which caused dead loop. Add several new
functions to emulate GLib memory managment.
*main.c, mad.[ch]: Add a new switch "-M", which allows to redirect MAD
messages to the file.
* util.[ch], utilunix.c: Modified, deleted our variants of strcasecmp()
and strdup() - we have g_ equivalences. Remove get_full_name() - it is
similar to concat_dir_and_file(). Some other tricks with g_* functions.
* global.h: Modified, extended. Now it is main memory mangment include -
i.e. all inclusions of <stdlib.h>, <malloc.h>, <glib.h>, "fs.h", "mem.h",
"util.h" and "mad.h" done there. This elimanates problem with proper or-
der of #include's.
* All around the source - changed order of #include's, most of them gone
to global.h (see above), minor changes, like "0" -> NULL in string func-
tions.
1999-01-27 04:08:30 +03:00
|
|
|
p = g_new (key_def, 1);
|
1998-02-27 07:54:42 +03:00
|
|
|
if (!base) base = p;
|
|
|
|
if (attach) attach->child = p;
|
|
|
|
|
|
|
|
p->ch = *seq;
|
|
|
|
p->code = code;
|
|
|
|
p->child = p->next = NULL;
|
|
|
|
if (!seq[1])
|
|
|
|
p->action = action;
|
|
|
|
else
|
|
|
|
p->action = MCKEY_NOACTION;
|
|
|
|
attach = p;
|
|
|
|
}
|
|
|
|
return base;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The maximum sequence length (32 + null terminator) */
|
|
|
|
static int seq_buffer [33];
|
|
|
|
static int *seq_append = 0;
|
|
|
|
|
|
|
|
static int push_char (int c)
|
|
|
|
{
|
|
|
|
if (!seq_append)
|
|
|
|
seq_append = seq_buffer;
|
|
|
|
|
|
|
|
if (seq_append == &(seq_buffer [sizeof (seq_buffer)-2]))
|
|
|
|
return 0;
|
|
|
|
*(seq_append++) = c;
|
|
|
|
*seq_append = 0;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2001-08-14 08:48:26 +04:00
|
|
|
/*
|
|
|
|
* Return 1 on success, 0 on error.
|
|
|
|
* An error happens if SEQ is a beginning of an existing longer sequence.
|
|
|
|
*/
|
|
|
|
int define_sequence (int code, char *seq, int action)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
|
|
|
key_def *base;
|
|
|
|
|
|
|
|
if (strlen (seq) > sizeof (seq_buffer)-1)
|
2001-08-14 08:48:26 +04:00
|
|
|
return 0;
|
1998-02-27 07:54:42 +03:00
|
|
|
|
|
|
|
for (base = keys; (base != 0) && *seq; ){
|
|
|
|
if (*seq == base->ch){
|
|
|
|
if (base->child == 0){
|
|
|
|
if (*(seq+1)){
|
|
|
|
base->child = create_sequence (seq+1, code, action);
|
2001-08-14 08:48:26 +04:00
|
|
|
return 1;
|
1998-02-27 07:54:42 +03:00
|
|
|
} else {
|
2001-08-14 08:48:26 +04:00
|
|
|
/* The sequence matches an existing one. */
|
1998-06-01 00:27:44 +04:00
|
|
|
base->code = code;
|
|
|
|
base->action = action;
|
2001-08-14 08:48:26 +04:00
|
|
|
return 1;
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
base = base->child;
|
|
|
|
seq++;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (base->next)
|
|
|
|
base = base->next;
|
|
|
|
else {
|
|
|
|
base->next = create_sequence (seq, code, action);
|
2001-08-14 08:48:26 +04:00
|
|
|
return 1;
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2001-08-14 08:48:26 +04:00
|
|
|
|
|
|
|
if (!*seq) {
|
|
|
|
/* Attempt to redefine a sequence with a shorter sequence. */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1998-02-27 07:54:42 +03:00
|
|
|
keys = create_sequence (seq, code, action);
|
2001-08-14 08:48:26 +04:00
|
|
|
return 1;
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static int *pending_keys;
|
|
|
|
|
1998-12-03 00:27:27 +03:00
|
|
|
static int
|
|
|
|
correct_key_code (int c)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
|
|
|
/* This is needed on some OS that do not support ncurses and */
|
|
|
|
/* do some magic after read()ing the data */
|
|
|
|
if (c == '\r')
|
|
|
|
return '\n';
|
|
|
|
|
|
|
|
#ifdef IS_AIX
|
|
|
|
if (c == KEY_SCANCEL)
|
|
|
|
return '\t';
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (c == KEY_F(0))
|
|
|
|
return KEY_F(10);
|
1998-04-01 02:36:24 +04:00
|
|
|
|
|
|
|
if (!alternate_plus_minus)
|
|
|
|
switch (c) {
|
|
|
|
case KEY_KP_ADD: c = '+'; break;
|
|
|
|
case KEY_KP_SUBTRACT: c = '-'; break;
|
|
|
|
case KEY_KP_MULTIPLY: c = '*'; break;
|
|
|
|
}
|
1998-02-27 07:54:42 +03:00
|
|
|
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
|
|
|
int get_key_code (int no_delay)
|
|
|
|
{
|
|
|
|
int c;
|
|
|
|
static key_def *this = NULL, *parent;
|
|
|
|
static struct timeval esctime = { -1, -1 };
|
|
|
|
static int lastnodelay = -1;
|
|
|
|
|
|
|
|
if (no_delay != lastnodelay) {
|
|
|
|
this = NULL;
|
|
|
|
lastnodelay = no_delay;
|
|
|
|
}
|
|
|
|
|
|
|
|
pend_send:
|
|
|
|
if (pending_keys){
|
|
|
|
int d = *pending_keys++;
|
|
|
|
check_pend:
|
|
|
|
if (!*pending_keys){
|
|
|
|
pending_keys = 0;
|
|
|
|
seq_append = 0;
|
|
|
|
}
|
|
|
|
if (d == ESC_CHAR && pending_keys){
|
|
|
|
d = ALT(*pending_keys++);
|
|
|
|
goto check_pend;
|
|
|
|
}
|
|
|
|
if ((d & 0x80) && use_8th_bit_as_meta)
|
|
|
|
d = ALT(d & 0x7f);
|
|
|
|
this = NULL;
|
|
|
|
return correct_key_code (d);
|
|
|
|
}
|
|
|
|
|
|
|
|
nodelay_try_again:
|
|
|
|
if (no_delay) {
|
|
|
|
#ifdef BUGGY_CURSES
|
|
|
|
wtimeout(stdscr, 500);
|
|
|
|
#else
|
|
|
|
nodelay (stdscr, TRUE);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
c = xgetch ();
|
|
|
|
if (no_delay) {
|
|
|
|
#ifdef BUGGY_CURSES
|
|
|
|
notimeout (stdscr, TRUE);
|
|
|
|
#else
|
|
|
|
nodelay (stdscr, FALSE);
|
|
|
|
#endif
|
|
|
|
if (c == ERR) {
|
|
|
|
if (this != NULL && parent != NULL &&
|
|
|
|
parent->action == MCKEY_ESCAPE && old_esc_mode) {
|
|
|
|
struct timeval current, timeout;
|
|
|
|
|
|
|
|
if (esctime.tv_sec == -1)
|
|
|
|
return ERR;
|
|
|
|
GET_TIME (current);
|
|
|
|
timeout.tv_sec = ESCMODE_TIMEOUT / 1000000 + esctime.tv_sec;
|
|
|
|
timeout.tv_usec = ESCMODE_TIMEOUT % 1000000 + esctime.tv_usec;
|
|
|
|
if (timeout.tv_usec > 1000000) {
|
|
|
|
timeout.tv_usec -= 1000000;
|
|
|
|
timeout.tv_sec++;
|
|
|
|
}
|
|
|
|
if (current.tv_sec < timeout.tv_sec)
|
|
|
|
return ERR;
|
|
|
|
if (current.tv_sec == timeout.tv_sec &&
|
|
|
|
current.tv_usec < timeout.tv_usec)
|
|
|
|
return ERR;
|
|
|
|
this = NULL;
|
|
|
|
pending_keys = seq_append = NULL;
|
|
|
|
return ESC_CHAR;
|
|
|
|
}
|
|
|
|
return ERR;
|
|
|
|
}
|
|
|
|
} else if (c == ERR){
|
|
|
|
/* Maybe we got an incomplete match.
|
|
|
|
This we do only in delay mode, since otherwise
|
|
|
|
xgetch can return ERR at any time. */
|
|
|
|
if (seq_append) {
|
|
|
|
pending_keys = seq_buffer;
|
|
|
|
goto pend_send;
|
|
|
|
}
|
|
|
|
this = NULL;
|
|
|
|
return ERR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Search the key on the root */
|
|
|
|
if (!no_delay || this == NULL) {
|
|
|
|
this = keys;
|
|
|
|
parent = NULL;
|
|
|
|
|
|
|
|
if ((c & 0x80) && use_8th_bit_as_meta) {
|
1998-06-01 00:27:44 +04:00
|
|
|
c &= 0x7f;
|
1998-02-27 07:54:42 +03:00
|
|
|
|
|
|
|
/* The first sequence defined starts with esc */
|
|
|
|
parent = keys;
|
|
|
|
this = keys->child;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while (this){
|
|
|
|
if (c == this->ch){
|
|
|
|
if (this->child){
|
|
|
|
if (!push_char (c)){
|
|
|
|
pending_keys = seq_buffer;
|
|
|
|
goto pend_send;
|
|
|
|
}
|
|
|
|
parent = this;
|
|
|
|
this = this->child;
|
|
|
|
if (parent->action == MCKEY_ESCAPE && old_esc_mode) {
|
|
|
|
if (no_delay) {
|
|
|
|
GET_TIME (esctime);
|
|
|
|
if (this == NULL) {
|
|
|
|
/* Shouldn't happen */
|
|
|
|
fprintf (stderr, "Internal error\n");
|
|
|
|
exit (1);
|
|
|
|
}
|
|
|
|
goto nodelay_try_again;
|
|
|
|
}
|
|
|
|
esctime.tv_sec = -1;
|
|
|
|
c = xgetch_second ();
|
|
|
|
if (c == ERR) {
|
|
|
|
pending_keys = seq_append = NULL;
|
|
|
|
this = NULL;
|
|
|
|
return ESC_CHAR;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (no_delay)
|
|
|
|
goto nodelay_try_again;
|
|
|
|
c = xgetch ();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* We got a complete match, return and reset search */
|
|
|
|
int code;
|
|
|
|
|
|
|
|
pending_keys = seq_append = NULL;
|
|
|
|
code = this->code;
|
|
|
|
this = NULL;
|
|
|
|
return correct_key_code (code);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (this->next)
|
|
|
|
this = this->next;
|
|
|
|
else {
|
|
|
|
if (parent != NULL && parent->action == MCKEY_ESCAPE) {
|
|
|
|
/* This is just to save a lot of define_sequences */
|
1998-04-08 22:50:24 +04:00
|
|
|
if (isalpha(c)
|
1998-02-27 07:54:42 +03:00
|
|
|
|| (c == '\n') || (c == '\t') || (c == XCTRL('h'))
|
|
|
|
|| (c == KEY_BACKSPACE) || (c == '!') || (c == '\r')
|
|
|
|
|| c == 127 || c == '+' || c == '-' || c == '\\'
|
|
|
|
|| c == '?')
|
|
|
|
c = ALT(c);
|
|
|
|
else if (isdigit(c))
|
|
|
|
c = KEY_F (c-'0');
|
|
|
|
else if (c == ' ')
|
|
|
|
c = ESC_CHAR;
|
|
|
|
pending_keys = seq_append = NULL;
|
|
|
|
this = NULL;
|
|
|
|
return correct_key_code (c);
|
|
|
|
}
|
|
|
|
/* Did not find a match or {c} was changed in the if above,
|
|
|
|
so we have to return everything we had skipped
|
|
|
|
*/
|
|
|
|
push_char (c);
|
|
|
|
pending_keys = seq_buffer;
|
|
|
|
goto pend_send;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
this = NULL;
|
|
|
|
return correct_key_code (c);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If set timeout is set, then we wait 0.1 seconds, else, we block */
|
1998-12-03 00:27:27 +03:00
|
|
|
static void
|
|
|
|
try_channels (int set_timeout)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
|
|
|
struct timeval timeout;
|
|
|
|
static fd_set select_set;
|
|
|
|
struct timeval *timeptr;
|
|
|
|
int v;
|
|
|
|
|
|
|
|
while (1){
|
|
|
|
FD_ZERO (&select_set);
|
|
|
|
FD_SET (input_fd, &select_set); /* Add stdin */
|
|
|
|
add_selects (&select_set);
|
|
|
|
|
|
|
|
if (set_timeout){
|
|
|
|
timeout.tv_sec = 0;
|
|
|
|
timeout.tv_usec = 100000;
|
|
|
|
timeptr = &timeout;
|
|
|
|
} else
|
|
|
|
timeptr = 0;
|
|
|
|
|
|
|
|
v = select (FD_SETSIZE, &select_set, NULL, NULL, timeptr);
|
|
|
|
if (v > 0){
|
|
|
|
check_selects (&select_set);
|
|
|
|
if (FD_ISSET (input_fd, &select_set))
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Workaround for System V Curses vt100 bug */
|
|
|
|
static int getch_with_delay (void)
|
|
|
|
{
|
|
|
|
int c;
|
|
|
|
|
|
|
|
/* This routine could be used on systems without mouse support,
|
|
|
|
so we need to do the select check :-( */
|
|
|
|
while (1){
|
|
|
|
if (!pending_keys)
|
|
|
|
try_channels (0);
|
|
|
|
|
|
|
|
/* Try to get a character */
|
|
|
|
c = get_key_code (0);
|
|
|
|
if (c != ERR)
|
|
|
|
break;
|
|
|
|
/* Failed -> wait 0.1 secs and try again */
|
|
|
|
try_channels (1);
|
|
|
|
}
|
|
|
|
/* Success -> return the character */
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef HAVE_LIBGPM
|
|
|
|
#define gpm_flag 0
|
|
|
|
#endif
|
|
|
|
|
|
|
|
extern int max_dirt_limit;
|
|
|
|
|
|
|
|
/* Returns a character read from stdin with appropriate interpretation */
|
|
|
|
/* Also takes care of generated mouse events */
|
|
|
|
/* Returns EV_MOUSE if it is a mouse event */
|
|
|
|
/* Returns EV_NONE if non-blocking or interrupt set and nothing was done */
|
|
|
|
int get_event (Gpm_Event *event, int redo_event, int block)
|
|
|
|
{
|
|
|
|
int c;
|
|
|
|
static int flag; /* Return value from select */
|
|
|
|
#ifdef HAVE_LIBGPM
|
|
|
|
static Gpm_Event ev; /* Mouse event */
|
|
|
|
#endif
|
|
|
|
struct timeval timeout;
|
|
|
|
struct timeval *time_addr = NULL;
|
|
|
|
static int dirty = 3;
|
|
|
|
|
|
|
|
if ((dirty == 3) || is_idle ()){
|
|
|
|
mc_refresh ();
|
|
|
|
doupdate ();
|
|
|
|
dirty = 1;
|
|
|
|
} else
|
|
|
|
dirty++;
|
|
|
|
|
|
|
|
vfs_timeout_handler ();
|
|
|
|
|
|
|
|
/* Ok, we use (event->x < 0) to signal that the event does not contain
|
|
|
|
a suitable position for the mouse, so we can't use show_mouse_pointer
|
|
|
|
on it.
|
|
|
|
*/
|
|
|
|
if (event->x > 0){
|
|
|
|
show_mouse_pointer (event->x, event->y);
|
|
|
|
if (!redo_event)
|
|
|
|
event->x = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Repeat if using mouse */
|
|
|
|
while ((xmouse_flag || gpm_flag) && !pending_keys)
|
|
|
|
{
|
|
|
|
if (xmouse_flag || gpm_flag)
|
|
|
|
{
|
|
|
|
FD_ZERO (&select_set);
|
|
|
|
FD_SET (input_fd, &select_set);
|
|
|
|
add_selects (&select_set);
|
|
|
|
|
|
|
|
#ifdef HAVE_LIBGPM
|
|
|
|
if (gpm_flag) {
|
|
|
|
FD_SET (gpm_fd, &select_set);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (redo_event){
|
|
|
|
timeout.tv_usec = mou_auto_repeat * 1000;
|
|
|
|
timeout.tv_sec = 0;
|
|
|
|
|
|
|
|
time_addr = &timeout;
|
|
|
|
} else {
|
|
|
|
int seconds;
|
|
|
|
|
|
|
|
if ((seconds = vfs_timeouts ())){
|
|
|
|
/* the timeout could be improved and actually be
|
|
|
|
* the number of seconds until the next vfs entry
|
|
|
|
* timeouts in the stamp list.
|
|
|
|
*/
|
|
|
|
|
|
|
|
timeout.tv_sec = seconds;
|
|
|
|
timeout.tv_usec = 0;
|
|
|
|
time_addr = &timeout;
|
|
|
|
} else
|
|
|
|
time_addr = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!block){
|
|
|
|
time_addr = &timeout;
|
|
|
|
timeout.tv_sec = 0;
|
|
|
|
timeout.tv_usec = 0;
|
|
|
|
}
|
|
|
|
enable_interrupt_key ();
|
|
|
|
flag = select (FD_SETSIZE, &select_set, NULL, NULL, time_addr);
|
|
|
|
disable_interrupt_key ();
|
|
|
|
|
|
|
|
/* select timed out: it could be for any of the following reasons:
|
|
|
|
* redo_event -> it was because of the MOU_REPEAT handler
|
|
|
|
* !block -> we did not block in the select call
|
|
|
|
* else -> 10 second timeout to check the vfs status.
|
|
|
|
*/
|
|
|
|
if (flag == 0){
|
|
|
|
if (redo_event)
|
|
|
|
return EV_MOUSE;
|
|
|
|
if (!block)
|
|
|
|
return EV_NONE;
|
|
|
|
vfs_timeout_handler ();
|
|
|
|
}
|
|
|
|
if (flag == -1 && errno == EINTR)
|
|
|
|
return EV_NONE;
|
|
|
|
|
|
|
|
check_selects (&select_set);
|
|
|
|
|
|
|
|
if (FD_ISSET (input_fd, &select_set))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
#ifdef HAVE_LIBGPM
|
|
|
|
if (gpm_flag && FD_ISSET (gpm_fd, &select_set)){
|
|
|
|
if (gpm_flag){
|
|
|
|
Gpm_GetEvent (&ev);
|
|
|
|
Gpm_FitEvent (&ev);
|
|
|
|
}
|
|
|
|
*event = ev;
|
|
|
|
return EV_MOUSE;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
# ifndef HAVE_SLANG
|
|
|
|
flag = is_wintouched(stdscr);
|
|
|
|
untouchwin (stdscr);
|
|
|
|
# endif
|
|
|
|
c = block ? getch_with_delay () : get_key_code(1);
|
1998-12-02 08:18:20 +03:00
|
|
|
|
1998-02-27 07:54:42 +03:00
|
|
|
# ifndef HAVE_SLANG
|
|
|
|
if (flag)
|
|
|
|
touchwin (stdscr);
|
|
|
|
# endif
|
|
|
|
|
|
|
|
if (c == MCKEY_MOUSE) { /* Mouse event */
|
|
|
|
xmouse_get_event (event);
|
2001-08-18 23:27:31 +04:00
|
|
|
if (event->type)
|
|
|
|
return EV_MOUSE;
|
|
|
|
else
|
|
|
|
return EV_NONE;
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return c;
|
1998-12-02 08:18:20 +03:00
|
|
|
}
|
1998-02-27 07:54:42 +03:00
|
|
|
|
|
|
|
/* Returns a key press, mouse events are discarded */
|
|
|
|
int mi_getch ()
|
|
|
|
{
|
|
|
|
Gpm_Event ev;
|
|
|
|
int key;
|
1998-04-15 10:05:34 +04:00
|
|
|
|
1998-04-15 10:15:42 +04:00
|
|
|
ev.x = -1;
|
2001-03-03 02:04:52 +03:00
|
|
|
while ((key = get_event (&ev, 0, 1)) == EV_NONE)
|
1998-02-27 07:54:42 +03:00
|
|
|
;
|
|
|
|
return key;
|
|
|
|
}
|
|
|
|
|
2001-07-20 20:19:28 +04:00
|
|
|
static int xgetch_second (void)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
|
|
|
fd_set Read_FD_Set;
|
|
|
|
int c;
|
|
|
|
struct timeval timeout;
|
|
|
|
|
|
|
|
timeout.tv_sec = ESCMODE_TIMEOUT / 1000000;
|
|
|
|
timeout.tv_usec = ESCMODE_TIMEOUT % 1000000;
|
|
|
|
#ifdef BUGGY_CURSES
|
|
|
|
wtimeout(stdscr, 500);
|
|
|
|
#else
|
|
|
|
nodelay (stdscr, TRUE);
|
|
|
|
#endif
|
|
|
|
FD_ZERO (&Read_FD_Set);
|
|
|
|
FD_SET (input_fd, &Read_FD_Set);
|
|
|
|
select (FD_SETSIZE, &Read_FD_Set, NULL, NULL, &timeout);
|
|
|
|
c = xgetch ();
|
|
|
|
#ifdef BUGGY_CURSES
|
|
|
|
notimeout (stdscr, TRUE);
|
|
|
|
#else
|
|
|
|
nodelay (stdscr, FALSE);
|
|
|
|
#endif
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
1998-12-03 00:27:27 +03:00
|
|
|
static void
|
|
|
|
learn_store_key (char *buffer, char **p, int c)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
|
|
|
if (*p - buffer > 253)
|
|
|
|
return;
|
|
|
|
if (c == ESC_CHAR) {
|
|
|
|
*(*p)++ = '\\';
|
|
|
|
*(*p)++ = 'e';
|
|
|
|
} else if (c < ' ') {
|
|
|
|
*(*p)++ = '^';
|
|
|
|
*(*p)++ = c + 'a' - 1;
|
|
|
|
} else if (c == '^') {
|
|
|
|
*(*p)++ = '^';
|
|
|
|
*(*p)++ = '^';
|
|
|
|
} else
|
|
|
|
*(*p)++ = (char) c;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *learn_key (void)
|
|
|
|
{
|
|
|
|
/* LEARN_TIMEOUT in usec */
|
|
|
|
#define LEARN_TIMEOUT 200000
|
|
|
|
|
|
|
|
fd_set Read_FD_Set;
|
|
|
|
struct timeval endtime;
|
|
|
|
struct timeval timeout;
|
|
|
|
int c = xgetch ();
|
|
|
|
char buffer [256];
|
|
|
|
char *p = buffer;
|
|
|
|
|
|
|
|
while (c == ERR)
|
|
|
|
c = xgetch (); /* Sanity check, should be unnecessary */
|
|
|
|
learn_store_key (buffer, &p, c);
|
|
|
|
GET_TIME (endtime);
|
|
|
|
endtime.tv_usec += LEARN_TIMEOUT;
|
|
|
|
if (endtime.tv_usec > 1000000) {
|
|
|
|
endtime.tv_usec -= 1000000;
|
|
|
|
endtime.tv_sec++;
|
|
|
|
}
|
|
|
|
#ifdef BUGGY_CURSES
|
|
|
|
wtimeout(stdscr, 500);
|
|
|
|
#else
|
|
|
|
nodelay (stdscr, TRUE);
|
|
|
|
#endif
|
|
|
|
for (;;) {
|
|
|
|
while ((c = xgetch ()) == ERR) {
|
|
|
|
GET_TIME (timeout);
|
|
|
|
timeout.tv_usec = endtime.tv_usec - timeout.tv_usec;
|
|
|
|
if (timeout.tv_usec < 0)
|
|
|
|
timeout.tv_sec++;
|
|
|
|
timeout.tv_sec = endtime.tv_sec - timeout.tv_sec;
|
|
|
|
if (timeout.tv_sec >= 0 && timeout.tv_usec > 0) {
|
|
|
|
FD_ZERO (&Read_FD_Set);
|
|
|
|
FD_SET (input_fd, &Read_FD_Set);
|
|
|
|
select (FD_SETSIZE, &Read_FD_Set, NULL, NULL, &timeout);
|
|
|
|
} else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (c == ERR)
|
|
|
|
break;
|
|
|
|
learn_store_key (buffer, &p, c);
|
|
|
|
}
|
|
|
|
#ifdef BUGGY_CURSES
|
|
|
|
notimeout (stdscr, TRUE);
|
|
|
|
#else
|
|
|
|
nodelay (stdscr, FALSE);
|
|
|
|
#endif
|
|
|
|
*p = 0;
|
Glibing..... (2)
Wed Jan 27 03:17:44 1999 Timur Bakeyev <mc@bat.ru>
* Converted memory managment to Glib. Now we use g_new()/g_malloc()/
g_strdup()/g_free() routings. Also, copy_strings() replaced by
g_strconcat(), strcasecmp() -> g_strcasecmp(),and sprintf() by
g_snprintf().
* Some sequences of malloc()/sprintf() changed to g_strdup_printf().
* mad.[ch]: Modified, to work with new GLib's memory managment. Fixed
a missing #undef for tempnam, which caused dead loop. Add several new
functions to emulate GLib memory managment.
*main.c, mad.[ch]: Add a new switch "-M", which allows to redirect MAD
messages to the file.
* util.[ch], utilunix.c: Modified, deleted our variants of strcasecmp()
and strdup() - we have g_ equivalences. Remove get_full_name() - it is
similar to concat_dir_and_file(). Some other tricks with g_* functions.
* global.h: Modified, extended. Now it is main memory mangment include -
i.e. all inclusions of <stdlib.h>, <malloc.h>, <glib.h>, "fs.h", "mem.h",
"util.h" and "mad.h" done there. This elimanates problem with proper or-
der of #include's.
* All around the source - changed order of #include's, most of them gone
to global.h (see above), minor changes, like "0" -> NULL in string func-
tions.
1999-01-27 04:08:30 +03:00
|
|
|
return g_strdup (buffer);
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
1998-04-01 02:36:24 +04:00
|
|
|
|
|
|
|
/* xterm and linux console only: set keypad to numeric or application
|
|
|
|
mode. Only in application keypad mode it's possible to distinguish
|
|
|
|
the '+' key and the '+' on the keypad ('*' and '-' ditto)*/
|
|
|
|
void
|
|
|
|
numeric_keypad_mode (void)
|
|
|
|
{
|
|
|
|
if (console_flag || xterm_flag) {
|
|
|
|
fprintf (stdout, "\033>");
|
|
|
|
fflush (stdout);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
application_keypad_mode (void)
|
|
|
|
{
|
|
|
|
if (console_flag || xterm_flag) {
|
|
|
|
fprintf (stdout, "\033=");
|
|
|
|
fflush (stdout);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-02-27 07:54:42 +03:00
|
|
|
|
|
|
|
/* A function to check if we're idle.
|
|
|
|
Currently checks only for key presses.
|
|
|
|
We could also check the mouse. */
|
|
|
|
int is_idle (void)
|
|
|
|
{
|
|
|
|
/* Check for incoming key presses *
|
|
|
|
* If there are any we say we're busy */
|
|
|
|
|
|
|
|
fd_set select_set;
|
|
|
|
struct timeval timeout;
|
|
|
|
FD_ZERO (&select_set);
|
|
|
|
FD_SET (0, &select_set);
|
|
|
|
timeout.tv_sec = 0;
|
|
|
|
timeout.tv_usec = 0;
|
|
|
|
select (FD_SETSIZE, &select_set, 0, 0, &timeout);
|
|
|
|
return ! FD_ISSET (0, &select_set);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1998-12-03 00:27:27 +03:00
|
|
|
int
|
|
|
|
get_modifier (void)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
2001-06-05 20:41:44 +04:00
|
|
|
#ifdef HAVE_TEXTMODE_X11_SUPPORT
|
2001-06-06 02:08:31 +04:00
|
|
|
if (x11_display) {
|
1999-04-21 23:18:31 +04:00
|
|
|
Window root, child;
|
|
|
|
int root_x, root_y;
|
|
|
|
int win_x, win_y;
|
|
|
|
unsigned int mask;
|
|
|
|
Bool b;
|
|
|
|
int result = 0;
|
|
|
|
|
2001-06-06 02:08:31 +04:00
|
|
|
b = XQueryPointer(x11_display, x11_window, &root, &child,
|
1999-04-21 23:18:31 +04:00
|
|
|
&root_x, &root_y,
|
|
|
|
&win_x, &win_y,
|
|
|
|
&mask);
|
|
|
|
|
|
|
|
if (mask & ShiftMask)
|
|
|
|
result |= SHIFT_PRESSED;
|
|
|
|
if (mask & ControlMask)
|
|
|
|
result |= CONTROL_PRESSED;
|
|
|
|
return result;
|
|
|
|
} else
|
|
|
|
#endif
|
1998-02-27 07:54:42 +03:00
|
|
|
#ifdef __linux__
|
1999-04-21 23:18:31 +04:00
|
|
|
{
|
|
|
|
unsigned char modifiers;
|
1998-02-27 07:54:42 +03:00
|
|
|
|
1999-04-21 23:18:31 +04:00
|
|
|
modifiers = 6;
|
1998-02-27 07:54:42 +03:00
|
|
|
|
1999-04-21 23:18:31 +04:00
|
|
|
if (ioctl (0, TIOCLINUX, &modifiers) < 0)
|
|
|
|
return 0;
|
1998-02-27 07:54:42 +03:00
|
|
|
|
1999-04-21 23:18:31 +04:00
|
|
|
return (int) modifiers;
|
|
|
|
}
|
1998-02-27 07:54:42 +03:00
|
|
|
#else
|
|
|
|
return 0;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
1998-12-03 00:27:27 +03:00
|
|
|
int
|
2001-06-26 07:20:22 +04:00
|
|
|
ctrl_pressed (void)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
|
|
|
if (get_modifier () & CONTROL_PRESSED)
|
|
|
|
return 1;
|
2001-06-26 07:20:22 +04:00
|
|
|
else
|
|
|
|
return 0;
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef HAVE_MAD
|
2001-06-06 02:08:31 +04:00
|
|
|
static void k_dispose (key_def *k)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
|
|
|
if (!k)
|
|
|
|
return;
|
|
|
|
k_dispose (k->child);
|
|
|
|
k_dispose (k->next);
|
Glibing..... (2)
Wed Jan 27 03:17:44 1999 Timur Bakeyev <mc@bat.ru>
* Converted memory managment to Glib. Now we use g_new()/g_malloc()/
g_strdup()/g_free() routings. Also, copy_strings() replaced by
g_strconcat(), strcasecmp() -> g_strcasecmp(),and sprintf() by
g_snprintf().
* Some sequences of malloc()/sprintf() changed to g_strdup_printf().
* mad.[ch]: Modified, to work with new GLib's memory managment. Fixed
a missing #undef for tempnam, which caused dead loop. Add several new
functions to emulate GLib memory managment.
*main.c, mad.[ch]: Add a new switch "-M", which allows to redirect MAD
messages to the file.
* util.[ch], utilunix.c: Modified, deleted our variants of strcasecmp()
and strdup() - we have g_ equivalences. Remove get_full_name() - it is
similar to concat_dir_and_file(). Some other tricks with g_* functions.
* global.h: Modified, extended. Now it is main memory mangment include -
i.e. all inclusions of <stdlib.h>, <malloc.h>, <glib.h>, "fs.h", "mem.h",
"util.h" and "mad.h" done there. This elimanates problem with proper or-
der of #include's.
* All around the source - changed order of #include's, most of them gone
to global.h (see above), minor changes, like "0" -> NULL in string func-
tions.
1999-01-27 04:08:30 +03:00
|
|
|
g_free (k);
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
|
2001-06-06 02:08:31 +04:00
|
|
|
static void s_dispose (SelectList *sel)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
|
|
|
if (!sel)
|
|
|
|
return;
|
|
|
|
|
|
|
|
s_dispose (sel->next);
|
Glibing..... (2)
Wed Jan 27 03:17:44 1999 Timur Bakeyev <mc@bat.ru>
* Converted memory managment to Glib. Now we use g_new()/g_malloc()/
g_strdup()/g_free() routings. Also, copy_strings() replaced by
g_strconcat(), strcasecmp() -> g_strcasecmp(),and sprintf() by
g_snprintf().
* Some sequences of malloc()/sprintf() changed to g_strdup_printf().
* mad.[ch]: Modified, to work with new GLib's memory managment. Fixed
a missing #undef for tempnam, which caused dead loop. Add several new
functions to emulate GLib memory managment.
*main.c, mad.[ch]: Add a new switch "-M", which allows to redirect MAD
messages to the file.
* util.[ch], utilunix.c: Modified, deleted our variants of strcasecmp()
and strdup() - we have g_ equivalences. Remove get_full_name() - it is
similar to concat_dir_and_file(). Some other tricks with g_* functions.
* global.h: Modified, extended. Now it is main memory mangment include -
i.e. all inclusions of <stdlib.h>, <malloc.h>, <glib.h>, "fs.h", "mem.h",
"util.h" and "mad.h" done there. This elimanates problem with proper or-
der of #include's.
* All around the source - changed order of #include's, most of them gone
to global.h (see above), minor changes, like "0" -> NULL in string func-
tions.
1999-01-27 04:08:30 +03:00
|
|
|
g_free (sel);
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
2001-06-06 02:08:31 +04:00
|
|
|
#endif /* HAVE_MAD */
|
1998-02-27 07:54:42 +03:00
|
|
|
|
|
|
|
void done_key ()
|
|
|
|
{
|
2001-06-06 02:08:31 +04:00
|
|
|
#ifdef HAVE_MAD
|
1998-02-27 07:54:42 +03:00
|
|
|
k_dispose (keys);
|
|
|
|
s_dispose (select_list);
|
|
|
|
#endif /* HAVE_MAD */
|
1999-04-21 23:18:31 +04:00
|
|
|
|
2001-06-05 20:41:44 +04:00
|
|
|
#ifdef HAVE_TEXTMODE_X11_SUPPORT
|
2001-06-06 02:08:31 +04:00
|
|
|
if (x11_display)
|
|
|
|
XCloseDisplay (x11_display);
|
2001-06-05 20:41:44 +04:00
|
|
|
#endif /* HAVE_TEXTMODE_X11_SUPPORT */
|
2001-06-06 02:08:31 +04:00
|
|
|
}
|