mc/nt/key.nt.c

311 lines
7.0 KiB
C

/* Keyboard support routines.
for Windows NT system.
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
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Bugs:
Have trouble with non-US keyboards, "Alt-gr"+keys (API tells CTRL-ALT is pressed)
*/
#include <config.h>
#ifndef _OS_NT
#error This file is for Win32 systems.
#else
#include <windows.h>
#include <stdio.h>
#include "mouse.h"
#include "global.h"
#include "main.h"
#include "key.h"
#include "../vfs/vfs.h"
#include "tty.h"
#include "util.debug.h"
/* Global variables */
int old_esc_mode = 0;
HANDLE hConsoleInput;
DWORD dwSaved_ControlState;
Gpm_Event evSaved_Event;
/* Unused variables */
int double_click_speed; /* they are here to keep linker happy */
int mou_auto_repeat;
int use_8th_bit_as_meta = 0;
/* Static Tables */
struct {
int key_code;
int vkcode;
} key_table [] = {
{ KEY_F(1), VK_F1 },
{ KEY_F(2), VK_F2 },
{ KEY_F(3), VK_F3 },
{ KEY_F(4), VK_F4 },
{ KEY_F(5), VK_F5 },
{ KEY_F(6), VK_F6 },
{ KEY_F(7), VK_F7 },
{ KEY_F(8), VK_F8 },
{ KEY_F(9), VK_F9 },
{ KEY_F(10), VK_F10 },
{ KEY_F(11), VK_F11 },
{ KEY_F(12), VK_F12 },
{ KEY_F(13), VK_F13 },
{ KEY_F(14), VK_F14 },
{ KEY_F(15), VK_F15 },
{ KEY_F(16), VK_F16 },
{ KEY_F(17), VK_F17 },
{ KEY_F(18), VK_F18 },
{ KEY_F(19), VK_F19 },
{ KEY_F(20), VK_F20 },
{ KEY_IC, VK_INSERT },
{ KEY_DC, VK_DELETE },
{ KEY_BACKSPACE, VK_BACK },
{ KEY_PPAGE, VK_PRIOR }, // Movement keys
{ KEY_NPAGE, VK_NEXT },
{ KEY_LEFT, VK_LEFT },
{ KEY_RIGHT, VK_RIGHT },
{ KEY_UP, VK_UP },
{ KEY_DOWN, VK_DOWN },
{ KEY_HOME, VK_HOME },
{ KEY_END, VK_END },
{ ALT('*'), VK_MULTIPLY }, // Numeric pad
{ ALT('+'), VK_ADD },
{ ALT('-'), VK_SUBTRACT },
{ ESC_CHAR, VK_ESCAPE }, /* ESC */
{ 0, 0}
};
/* init_key - Called in main.c to initialize ourselves
Get handle to console input
*/
void init_key (void)
{
win32APICALL_HANDLE (hConsoleInput, GetStdHandle (STD_INPUT_HANDLE));
}
int ctrl_pressed ()
{
return dwSaved_ControlState & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED);
}
int shift_pressed ()
{
return dwSaved_ControlState & SHIFT_PRESSED;
}
int alt_pressed ()
{
return dwSaved_ControlState & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED);
}
static int VKtoCurses (int a_vkc)
{
int i;
for (i = 0; key_table[i].vkcode != 0; i++)
if (a_vkc == key_table[i].vkcode) {
return key_table[i].key_code;
}
return 0;
}
static int translate_key_code(int asc, int scan)
{
int c;
c = VKtoCurses (scan);
if (!asc && !c)
return 0;
if (asc && c)
return c;
if (!asc)
{
if (shift_pressed() && (c >= KEY_F(1)) && (c <= KEY_F(10)))
c += 10;
if (alt_pressed() && (c >= KEY_F(1)) && (c <= KEY_F(2)))
c += 10;
if (alt_pressed() && (c == KEY_F(7)))
c = ALT('?');
if (ctrl_pressed() && c == '\t')
c = ALT('\t');
return c;
}
if (ctrl_pressed())
return XCTRL(asc);
if (alt_pressed())
return ALT(asc);
if (asc == 13)
return 10;
return asc;
}
int get_key_code (int no_delay)
{
INPUT_RECORD ir; /* Input record */
DWORD dw; /* number of records actually read */
int ch, vkcode, j;
if (no_delay) {
/* Check if any input pending, otherwise return */
nodelay (stdscr, TRUE);
win32APICALL(PeekConsoleInput(hConsoleInput, &ir, 1, &dw));
if (!dw)
return 0;
}
do {
win32APICALL(ReadConsoleInput(hConsoleInput, &ir, 1, &dw));
switch (ir.EventType) {
case KEY_EVENT:
if (!ir.Event.KeyEvent.bKeyDown) /* Process key just once: when pressed */
break;
vkcode = ir.Event.KeyEvent.wVirtualKeyCode;
ch = ir.Event.KeyEvent.uChar.AsciiChar;
dwSaved_ControlState = ir.Event.KeyEvent.dwControlKeyState;
j = translate_key_code (ch, vkcode);
if (j)
return j;
break;
case MOUSE_EVENT:
// Save event as a GPM-like event
evSaved_Event.x = ir.Event.MouseEvent.dwMousePosition.X;
evSaved_Event.y = ir.Event.MouseEvent.dwMousePosition.Y+1;
evSaved_Event.buttons = ir.Event.MouseEvent.dwButtonState;
switch (ir.Event.MouseEvent.dwEventFlags) {
case 0:
evSaved_Event.type = GPM_DOWN | GPM_SINGLE;
break;
case MOUSE_MOVED:
evSaved_Event.type = GPM_MOVE;
break;
case DOUBLE_CLICK:
evSaved_Event.type = GPM_DOWN | GPM_DOUBLE;
break;
};
return 0;
}
} while (!no_delay);
return 0;
}
static int getch_with_delay (void)
{
int c;
while (1) {
/* Try to get a character */
c = get_key_code (0);
if (c != ERR)
break;
}
/* Success -> return the character */
return c;
}
/* Returns a character read from stdin with appropriate interpretation */
int get_event (Gpm_Event *event, int redo_event, int block)
{
int c;
static int flag; /* Return value from select */
static int dirty = 3;
if ((dirty == 1) || is_idle ()){
refresh ();
doupdate ();
dirty = 1;
} else
dirty++;
vfs_timeout_handler ();
c = block ? getch_with_delay () : get_key_code (1);
if (!c) {
/* Code is 0, so this is a Control key or mouse event */
return EV_NONE; /* FIXME: mouse not supported */
}
return c;
}
/* Returns a key press, mouse events are discarded */
int mi_getch ()
{
Gpm_Event ev;
int key;
while ((key = get_event (&ev, 0, 1)) == 0)
;
return key;
}
/*
is_idle - A function to check if we're idle.
It checks for any waiting event (that can be a Key, Mouse event,
and other internal events like focus or menu)
*/
int is_idle (void)
{
DWORD dw;
if (GetNumberOfConsoleInputEvents (hConsoleInput, &dw))
if (dw > 15)
return 0;
return 1;
}
/* get_modifier */
int get_modifier()
{
int retval = 0;
if (dwSaved_ControlState & LEFT_ALT_PRESSED) /* code is not clean, because we return Linux-like bitcodes*/
retval |= ALTL_PRESSED;
if (dwSaved_ControlState & RIGHT_ALT_PRESSED)
retval |= ALTR_PRESSED;
if (dwSaved_ControlState & RIGHT_CTRL_PRESSED ||
dwSaved_ControlState & LEFT_CTRL_PRESSED)
retval |= CONTROL_PRESSED;
if (dwSaved_ControlState & SHIFT_PRESSED)
retval |= SHIFT_PRESSED;
return retval;
}
/* void functions for UNIX compatibility */
void define_sequence (int code, char* vkcode, int action)
{
}
void channels_up()
{
}
void channels_down()
{
}
void init_key_input_fd (void)
{
}
/* mouse is not yet supported, sorry */
void init_mouse (void) {}
void shut_mouse (void) {}
#endif /* _OS_NT */