#endif
#endif
+#include "sysselect.h"
+
#include "blockinput.h"
#undef NULL
#include "termopts.h"
#include "dispextern.h"
#include "process.h"
+#include "cm.h" /* for reset_sys_modes */
#ifdef WINDOWSNT
#include <direct.h>
void croak P_ ((char *));
#ifdef AIXHFT
-void hft_init ();
-void hft_reset ();
+void hft_init P_ ((struct tty_display_info *));
+void hft_reset P_ ((struct tty_display_info *));
#endif
/* Temporary used by `sigblock' when defined in terms of signprocmask. */
if (noninteractive)
return;
- /* Discarding input is not safe when the input could contain
- replies from the X server. So don't do it. */
- if (read_socket_hook)
- return;
-
#ifdef VMS
end_kbd_input ();
SYS$QIOW (0, fileno (TTY_INPUT (CURTTY())), IO$_READVBLK|IO$M_PURGE, input_iosb, 0, 0,
#else /* not VMS */
#ifdef APOLLO
{
- int zero = 0;
- ioctl (fileno (TTY_INPUT (CURTTY())), TIOCFLUSH, &zero);
+ struct tty_display_info *tty;
+ for (tty = tty_list; tty; tty = tty->next)
+ {
+ int zero = 0;
+ ioctl (fileno (TTY_INPUT (tty)), TIOCFLUSH, &zero);
+ }
}
#else /* not Apollo */
#ifdef MSDOS /* Demacs 1.1.1 91/10/16 HIRANO Satoshi */
;
#else /* not MSDOS */
{
- struct tty_output tty;
+ struct tty_display_info *tty;
for (tty = tty_list; tty; tty = tty->next)
{
EMACS_GET_TTY (fileno (TTY_INPUT (tty)), &buf);
#endif /* not WINDOWSNT */
}
+\f
#ifdef SIGTSTP
/* Arrange for character C to be read as the next input from
- the terminal. */
+ the terminal.
+ XXX What if we have multiple ttys?
+*/
void
-#ifdef PROTOTYPES
stuff_char (char c)
-#else
-stuff_char (c)
- char c;
-#endif
{
- if (read_socket_hook)
+ if (! FRAME_TERMCAP_P (SELECTED_FRAME ()))
return;
/* Should perhaps error if in batch mode */
#endif /* SIGTSTP */
\f
void
-init_baud_rate ()
+init_baud_rate (int fd)
{
if (noninteractive)
emacs_ospeed = 0;
#ifdef VMS
struct sensemode sg;
- SYS$QIOW (0, fileno (TTY_INPUT (CURTTY())), IO$_SENSEMODE, &sg, 0, 0,
+ SYS$QIOW (0, fd, IO$_SENSEMODE, &sg, 0, 0,
&sg.class, 12, 0, 0, 0, 0 );
emacs_ospeed = sg.xmit_baud;
#else /* not VMS */
struct termios sg;
sg.c_cflag = B9600;
- tcgetattr (fileno (TTY_INPUT (CURTTY())), &sg);
+ tcgetattr (fd, &sg);
emacs_ospeed = cfgetospeed (&sg);
#if defined (USE_GETOBAUD) && defined (getobaud)
/* m88k-motorola-sysv3 needs this (ghazi@noc.rutgers.edu) 9/1/94. */
sg.c_cflag = B9600;
#ifdef HAVE_TCATTR
- tcgetattr (fileno (TTY_INPUT (CURTTY())), &sg);
+ tcgetattr (fd, &sg);
#else
- ioctl (fileno (TTY_INPUT (CURTTY())), TCGETA, &sg);
+ ioctl (fd, TCGETA, &sg);
#endif
emacs_ospeed = sg.c_cflag & CBAUD;
#else /* neither VMS nor TERMIOS nor TERMIO */
struct sgttyb sg;
sg.sg_ospeed = B9600;
- if (ioctl (fileno (TTY_INPUT (CURTTY())), TIOCGETP, &sg) < 0)
+ if (ioctl (fd, TIOCGETP, &sg) < 0)
abort ();
emacs_ospeed = sg.sg_ospeed;
#endif /* not HAVE_TERMIO */
baud_rate = 1200;
}
+\f
/*ARGSUSED*/
void
set_exclusive_use (fd)
#ifdef BSD4_1
if (interrupt_input)
- reset_sigio ();
+ reset_sigio (0);
#endif /* BSD4_1 */
#ifdef RTU
{
}
}
\f
+#ifndef SIGIO
+/* If SIGIO is broken, don't do anything. */
+void
+init_sigio (int fd)
+{
+}
+
+void
+reset_sigio (int fd)
+{
+}
+
+void
+request_sigio (void)
+{
+}
+
+void
+unrequest_sigio (void)
+{
+}
+
+#else
#ifdef F_SETFL
-int old_fcntl_flags;
+int old_fcntl_flags[MAXDESC];
void
init_sigio (fd)
int fd;
{
#ifdef FASYNC
- old_fcntl_flags = fcntl (fd, F_GETFL, 0) & ~FASYNC;
- fcntl (fd, F_SETFL, old_fcntl_flags | FASYNC);
+ old_fcntl_flags[fd] = fcntl (fd, F_GETFL, 0) & ~FASYNC;
+ fcntl (fd, F_SETFL, old_fcntl_flags[fd] | FASYNC);
#endif
interrupts_deferred = 0;
}
void
-reset_sigio ()
+reset_sigio (fd)
+ int fd;
{
- unrequest_sigio ();
+#ifdef FASYNC
+ fcntl (fd, F_SETFL, old_fcntl_flags[fd]);
+#endif
}
#ifdef FASYNC /* F_SETFL does not imply existence of FASYNC */
+/* XXX Uhm, FASYNC is not used anymore here. */
void
request_sigio ()
{
+ /* XXX read_socket_hook is not global anymore. Is blocking SIGIO
+ bad under X? */
+#if 0
if (read_socket_hook)
return;
+#endif
#ifdef SIGWINCH
sigunblock (sigmask (SIGWINCH));
#endif
- fcntl (fileno (TTY_INPUT (CURTTY())), F_SETFL, old_fcntl_flags | FASYNC);
+ sigunblock (sigmask (SIGIO));
interrupts_deferred = 0;
}
void
-unrequest_sigio ()
-{
+unrequest_sigio (void)
+{
+ /* XXX read_socket_hook is not global anymore. Is blocking SIGIO
+ bad under X? */
+#if 0
if (read_socket_hook)
return;
-
+#endif
+
#ifdef SIGWINCH
sigblock (sigmask (SIGWINCH));
#endif
- fcntl (fileno (TTY_INPUT (CURTTY())), F_SETFL, old_fcntl_flags);
+ sigblock (sigmask (SIGIO));
interrupts_deferred = 1;
}
if (read_socket_hook)
return;
- ioctl (fileno (TTY_INPUT (CURTTY())), FIOASYNC, &on);
+ /* XXX CURTTY() is bogus here. */
+ ioctl (fileno (TTY_INPUT (CURTTY ())), FIOASYNC, &on);
interrupts_deferred = 0;
}
if (read_socket_hook)
return;
- ioctl (fileno (TTY_INPUT (CURTTY())), FIOASYNC, &off);
+ /* XXX CURTTY() is bogus here. */
+ ioctl (fileno (TTY_INPUT (CURTTY ())), FIOASYNC, &off);
interrupts_deferred = 1;
}
sigemptyset (&st);
sigaddset (&st, SIGIO);
- ioctl (fileno (TTY_INPUT (CURTTY())), FIOASYNC, &on);
+ ioctl (0, FIOASYNC, &on); /* XXX This fails for multiple ttys. */
interrupts_deferred = 0;
sigprocmask (SIG_UNBLOCK, &st, (sigset_t *)0);
}
if (read_socket_hook)
return;
- ioctl (fileno (TTY_INPUT (CURTTY())), FIOASYNC, &off);
+ ioctl (0, FIOASYNC, &off); /* XXX This fails for multiple ttys. */
interrupts_deferred = 1;
}
#endif /* STRIDE */
#endif /* FASYNC */
#endif /* F_SETFL */
+#endif /* SIGIO */
\f
/* Saving and restoring the process group of Emacs's terminal. */
group, redirect the TTY to point to our own process group. We need
to be in our own process group to receive SIGIO properly. */
void
-narrow_foreground_group ()
+narrow_foreground_group (int fd)
{
int me = getpid ();
- setpgrp (0, inherited_pgroup);
+ if (! inherited_pgroup)
+ inherited_pgroup = getpgid (0);
+ /* XXX This only works on the controlling tty. */
if (inherited_pgroup != me)
- EMACS_SET_TTY_PGRP (fileno (stdin), &me); /* stdin is intentional here */
- setpgrp (0, me);
+ EMACS_SET_TTY_PGRP (fd, &me);
+ setpgid (0, me);
}
/* Set the tty to our original foreground group. */
void
-widen_foreground_group ()
+widen_foreground_group (int fd)
{
if (inherited_pgroup != getpid ())
- EMACS_SET_TTY_PGRP (fileno (stdin), &inherited_pgroup); /* stdin is intentional here */
- setpgrp (0, inherited_pgroup);
+ EMACS_SET_TTY_PGRP (fd, &inherited_pgroup);
+ setpgid (0, inherited_pgroup);
}
#endif /* BSD_PGRPS */
#ifndef F_SETOWN_BUG
#ifdef F_SETOWN
-int old_fcntl_owner;
+int old_fcntl_owner[MAXDESC];
#endif /* F_SETOWN */
#endif /* F_SETOWN_BUG */
void
init_all_sys_modes (void)
{
- struct tty_output *tty = tty_list;
- while (tty) {
+ struct tty_display_info *tty;
+ for (tty = tty_list; tty; tty = tty->next)
init_sys_modes (tty);
- tty = tty->next;
- }
}
void
init_sys_modes (tty_out)
- struct tty_output *tty_out;
+ struct tty_display_info *tty_out;
{
struct emacs_tty tty;
#endif /* VMS */
#ifdef BSD_PGRPS
+#if 0
+ /* read_socket_hook is not global anymore. I think doing this
+ unconditionally will not cause any problems. */
if (! read_socket_hook && EQ (Vwindow_system, Qnil))
- narrow_foreground_group ();
+#endif
+ narrow_foreground_group (fileno (TTY_INPUT (tty_out)));
#endif
#ifdef HAVE_WINDOW_SYSTEM
/* Emacs' window system on MSDOG uses the `internal terminal' and therefore
needs the initialization code below. */
- if (!read_socket_hook && EQ (Vwindow_system, Qnil))
+ if (tty_out->input != stdin || EQ (Vwindow_system, Qnil))
#endif
{
- EMACS_GET_TTY (fileno (TTY_INPUT (tty_out)), &tty_out->old_tty);
-
- tty_out->old_tty_valid = 1;
+ if (! tty_out->old_tty)
+ tty_out->old_tty = (struct emacs_tty *) xmalloc (sizeof (struct emacs_tty));
+
+ EMACS_GET_TTY (fileno (TTY_INPUT (tty_out)), tty_out->old_tty);
- tty = tty_out->old_tty;
+ tty = *tty_out->old_tty;
#if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
- XSETINT (Vtty_erase_char, tty_out->old_tty.main.c_cc[VERASE]);
+ XSETINT (Vtty_erase_char, tty.main.c_cc[VERASE]);
#ifdef DGUX
/* This allows meta to be sent on 8th bit. */
tty.main.c_lflag &= ~IEXTEN; /* Disable other editing characters. */
#endif
tty.main.c_lflag |= ISIG; /* Enable signals */
- if (flow_control)
+ if (tty_out->flow_control)
{
tty.main.c_iflag |= IXON; /* Enable start/stop output control */
#ifdef IXANY
on output */
tty.main.c_oflag &= ~TAB3; /* Disable tab expansion */
#ifdef CS8
- if (meta_key)
+ if (tty_out->meta_key)
{
tty.main.c_cflag |= CS8; /* allow 8th bit on input */
tty.main.c_cflag &= ~PARENB;/* Don't check parity */
}
#endif
- tty.main.c_cc[VINTR] = quit_char; /* C-g (usually) gives SIGINT */
- /* Set up C-g for both SIGQUIT and SIGINT.
- We don't know which we will get, but we handle both alike
- so which one it really gives us does not matter. */
- tty.main.c_cc[VQUIT] = quit_char;
+ if (tty_out->input == stdin)
+ {
+ tty.main.c_cc[VINTR] = quit_char; /* C-g (usually) gives SIGINT */
+ /* Set up C-g for both SIGQUIT and SIGINT.
+ We don't know which we will get, but we handle both alike
+ so which one it really gives us does not matter. */
+ tty.main.c_cc[VQUIT] = quit_char;
+ }
+ else
+ {
+ /* We normally don't get interrupt or quit signals from tty
+ devices other than our controlling terminal; therefore,
+ we must handle C-g as normal input. Unfortunately, this
+ means that the interrupt and quit feature must be
+ disabled on secondary ttys, or we would not even see the
+ keypress.
+
+ Note that even though emacsclient could have special code
+ to pass SIGINT to Emacs, we should _not_ enable
+ interrupt/quit keys for emacsclient frames. This means
+ that we can't break out of loops in C code from a
+ secondary tty frame, but we can always decide what
+ display the C-g came from, which is more important from a
+ usability point of view. (Consider the case when two
+ people work together using the same Emacs instance.) */
+ tty.main.c_cc[VINTR] = CDISABLE;
+ tty.main.c_cc[VQUIT] = CDISABLE;
+ }
tty.main.c_cc[VMIN] = 1; /* Input should wait for at least 1 char */
tty.main.c_cc[VTIME] = 0; /* no matter how long that takes. */
#ifdef VSWTCH
tty.main.c_cc[VDISCARD] = CDISABLE;
#endif /* VDISCARD */
- if (flow_control)
+ if (tty_out->flow_control)
{
#ifdef VSTART
tty.main.c_cc[VSTART] = '\021';
tty.main.c_cc[VSUSP] = 255;
tty.main.c_cc[VDSUSP] = 255;
#endif /* IBMR2AIX */
- if (flow_control)
+ if (tty_out->flow_control)
{
#ifdef VSTART
tty.main.c_cc[VSTART] = '\021';
tty.main.tt_char |= TT$M_NOECHO;
if (meta_key)
tty.main.tt_char |= TT$M_EIGHTBIT;
- if (flow_control)
+ if (tty_out->flow_control)
tty.main.tt_char |= TT$M_TTSYNC;
else
tty.main.tt_char &= ~TT$M_TTSYNC;
set this */
tty.tchars = new_tchars;
tty.tchars.t_intrc = quit_char;
- if (flow_control)
+ if (tty_out->flow_control)
{
tty.tchars.t_startc = '\021';
tty.tchars.t_stopc = '\023';
we have an unlocked terminal at the start. */
#ifdef TCXONC
- if (!flow_control) ioctl (fileno (TTY_INPUT (tty_out)), TCXONC, 1);
+ if (!tty_out->flow_control) ioctl (fileno (TTY_INPUT (tty_out)), TCXONC, 1);
#endif
#ifndef APOLLO
#ifdef TIOCSTART
- if (!flow_control) ioctl (fileno (TTY_INPUT (tty_out)), TIOCSTART, 0);
+ if (!tty_out->flow_control) ioctl (fileno (TTY_INPUT (tty_out)), TIOCSTART, 0);
#endif
#endif
#if defined (HAVE_TERMIOS) || defined (HPUX9)
#ifdef TCOON
- if (!flow_control) tcflow (fileno (TTY_INPUT (tty_out)), TCOON);
+ if (!tty_out->flow_control) tcflow (fileno (TTY_INPUT (tty_out)), TCOON);
#endif
#endif
#ifdef AIXHFT
- hft_init ();
+ hft_init (tty_out);
#ifdef IBMR2AIX
{
/* IBM's HFT device usually thinks a ^J should be LF/CR. We need it
#ifndef F_SETOWN_BUG
#ifdef F_GETOWN /* F_SETFL does not imply existence of F_GETOWN */
if (interrupt_input
- && ! read_socket_hook && EQ (Vwindow_system, Qnil))
+ && (tty_out->input != stdin || EQ (Vwindow_system, Qnil)))
{
- old_fcntl_owner = fcntl (fileno (TTY_INPUT (tty_out)), F_GETOWN, 0);
+ old_fcntl_owner[fileno (TTY_INPUT (tty_out))] =
+ fcntl (fileno (TTY_INPUT (tty_out)), F_GETOWN, 0);
fcntl (fileno (TTY_INPUT (tty_out)), F_SETOWN, getpid ());
init_sigio (fileno (TTY_INPUT (tty_out)));
}
#else
setbuf (TTY_OUTPUT (tty_out), (char *) _sobuf);
#endif
+
+#if 0 /* We always need this with multi-tty support. */
#ifdef HAVE_WINDOW_SYSTEM
/* Emacs' window system on MSDOG uses the `internal terminal' and therefore
needs the initialization code below. */
#endif
)
#endif
- set_terminal_modes (tty_out);
+#endif
+ tty_set_terminal_modes (tty_out->display);
if (!tty_out->term_initted)
{
Lisp_Object tail, frame;
FOR_EACH_FRAME (tail, frame)
{
+ /* XXX This needs to be revised. */
if (FRAME_TERMCAP_P (XFRAME (frame))
&& FRAME_TTY (XFRAME (frame)) == tty_out)
init_frame_faces (XFRAME (frame));
At the time this is called, init_sys_modes has not been done yet. */
int
-tabs_safe_p ()
+tabs_safe_p (int fd)
{
- struct emacs_tty tty;
+ struct emacs_tty etty;
- EMACS_GET_TTY (fileno (TTY_INPUT (CURTTY())), &tty);
- return EMACS_TTY_TABS_OK (&tty);
+ EMACS_GET_TTY (fd, &etty);
+ return EMACS_TTY_TABS_OK (&etty);
}
\f
/* Get terminal size from system.
We store 0 if there's no valid information. */
void
-get_tty_size (tty_out, widthp, heightp)
- struct tty_output *tty_out;
- int *widthp, *heightp;
+get_tty_size (int fd, int *widthp, int *heightp)
{
#ifdef TIOCGWINSZ
/* BSD-style. */
struct winsize size;
- if (ioctl (fileno (TTY_INPUT (tty_out)), TIOCGWINSZ, &size) == -1)
+ if (ioctl (fd, TIOCGWINSZ, &size) == -1)
*widthp = *heightp = 0;
else
{
/* SunOS - style. */
struct ttysize size;
- if (ioctl (fileno (TTY_INPUT (tty_out)), TIOCGSIZE, &size) == -1)
+ if (ioctl (fd, TIOCGSIZE, &size) == -1)
*widthp = *heightp = 0;
else
{
struct sensemode tty;
- SYS$QIOW (0, fileno (TTY_INPUT (CURTTY())), IO$_SENSEMODE, &tty, 0, 0,
+ SYS$QIOW (0, fd, IO$_SENSEMODE, &tty, 0, 0,
&tty.class, 12, 0, 0, 0, 0);
*widthp = tty.scr_wid;
*heightp = tty.scr_len;
*widthp = 0;
*heightp = 0;
#endif
-
#endif /* not VMS */
#endif /* not SunOS-style */
#endif /* not BSD-style */
void
reset_all_sys_modes (void)
{
- struct tty_output *tty = tty_list;
- while (tty) {
+ struct tty_display_info *tty;
+ for (tty = tty_list; tty; tty = tty->next)
reset_sys_modes (tty);
- tty = tty->next;
- }
}
-/* Prepare the terminal for exiting Emacs; move the cursor to the
+/* Prepare the terminal for closing it; move the cursor to the
bottom of the frame, turn off interrupt-driven I/O, etc. */
void
reset_sys_modes (tty_out)
- struct tty_output *tty_out;
+ struct tty_display_info *tty_out;
{
- struct frame *sf;
-
if (noninteractive)
{
fflush (stdout);
}
if (!tty_out->term_initted)
return;
+#if 0 /* We always need to do this with multi-tty support. */
#ifdef HAVE_WINDOW_SYSTEM
/* Emacs' window system on MSDOG uses the `internal terminal' and therefore
needs the clean-up code below. */
- if (!EQ (Vwindow_system, Qnil)
+ if (tty_out->input != stdin
+ || (!EQ (Vwindow_system, Qnil)
#ifndef WINDOWSNT
/* When running in tty mode on NT/Win95, we have a read_socket
hook, but still need the rest of the clean-up code below. */
|| read_socket_hook
#endif
- )
+ ))
return;
#endif
- sf = SELECTED_FRAME ();
- cursor_to (FRAME_LINES (sf) - 1, 0);
- clear_end_of_line (FRAME_COLS (sf));
- /* clear_end_of_line may move the cursor */
- cursor_to (FRAME_LINES (sf) - 1, 0);
+#endif
+
+ cmgoto (tty_out, FrameRows (tty_out) - 1, 0);
+#if 0 /* XXX This doesn't work anymore, the signature has changed. */
+ tty_clear_end_of_line (tty_out, FrameCols (tty_out));
+#endif
+ cmgoto (tty_out, FrameRows (tty_out) - 1, 0);
+ fflush (tty_out->output);
+
#if defined (IBMR2AIX) && defined (AIXHFT)
{
/* HFT devices normally use ^J as a LF/CR. We forced it to
}
#endif
- reset_terminal_modes (tty_out);
+ tty_reset_terminal_modes (tty_out->display);
fflush (TTY_OUTPUT (tty_out));
#ifdef BSD_SYSTEM
#ifndef BSD4_1
/* Avoid possible loss of output when changing terminal modes. */
- fsync (TTY_OUTPUT (tty_out));
+ fsync (fileno (TTY_OUTPUT (tty_out)));
#endif
#endif
#ifdef F_SETOWN /* F_SETFL does not imply existence of F_SETOWN */
if (interrupt_input)
{
- reset_sigio ();
- fcntl (fileno (TTY_INPUT (tty_out)), F_SETOWN, old_fcntl_owner);
+ reset_sigio (fileno (TTY_INPUT (tty_out)));
+ fcntl (fileno (TTY_INPUT (tty_out)), F_SETOWN,
+ old_fcntl_owner[fileno (TTY_INPUT (tty_out))]);
}
#endif /* F_SETOWN */
#endif /* F_SETOWN_BUG */
#endif /* F_SETFL */
#ifdef BSD4_1
if (interrupt_input)
- reset_sigio ();
+ reset_sigio (fileno (TTY_INPUT (tty_out)));
#endif /* BSD4_1 */
- if (tty_out->old_tty_valid)
+ if (tty_out->old_tty)
while (EMACS_SET_TTY (fileno (TTY_INPUT (tty_out)),
- &tty_out->old_tty, 0) < 0 && errno == EINTR)
+ tty_out->old_tty, 0) < 0 && errno == EINTR)
;
#ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida */
#endif
#ifdef BSD_PGRPS
- widen_foreground_group ();
+ widen_foreground_group (fileno (TTY_INPUT (tty_out)));
#endif
}
\f
request_sigio ();
}
-reset_sigio ()
+reset_sigio (fd)
+ int fd;
{
unrequest_sigio ();
}
}
return ravail;
}
-#endif /* not WINDOWSNT */
+#endif not WINDOWSNT
/* Read keyboard input into the standard buffer,
waiting for at least one character. */
void
read_input_waiting ()
{
+ /* XXX This needs to be updated for multi-tty support. Does
+ anybody need to emulate select these days? */
int nread, i;
extern int quit_char;
}
}
+#if !defined (HAVE_SELECT) || defined (BROKEN_SELECT_NON_X)
+#define select sys_select
+#endif
+
#endif /* not HAVE_SELECT */
#endif /* not VMS */
#endif /* not MSDOS */
}
void
-reset_sigio ()
+reset_sigio (fd)
+ int fd;
{
if (noninteractive)
return;
lmode = ~LINTRUP & lmode;
- ioctl (0, TIOCLSET, &lmode);
+ ioctl (fd, TIOCLSET, &lmode);
}
void
#undef abort
sys_abort ()
{
- reset_sys_modes ();
+ reset_all_sys_modes ();
LIB$SIGNAL (SS$_DEBUG);
}
#endif /* abort */
/* Called from init_sys_modes. */
void
-hft_init ()
+hft_init (struct tty_display_info *tty_out)
{
int junk;
keymap.hfkey[1].hf_char = 127;
hftctl (0, HFSKBD, &buf);
}
- /* The HFT system on AIX doesn't optimize for scrolling, so it's really ugly
- at times. */
- TTY_LINE_INS_DEL_OK (CURTTY ()) = 0;
- TTY_CHAR_INS_DEL_OK (CURTTY ()) = 0;
}
/* Reset the rubout key to backspace. */
void
-hft_reset ()
+hft_reset (struct tty_display_info *tty_out)
{
struct hfbuf buf;
struct hfkeymap keymap;