735 lines
18 KiB
C
735 lines
18 KiB
C
|
/*
|
||
|
* Copyright (C) 1996-1998 Szeredi Miklos
|
||
|
* Email: mszeredi@inf.bme.hu
|
||
|
*
|
||
|
* 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. See the file COPYING.
|
||
|
*
|
||
|
* 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.
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
/* #define DEBUG_KEYS */
|
||
|
#include "misc.h"
|
||
|
|
||
|
#include "spkey.h"
|
||
|
#include "spkey_p.h"
|
||
|
|
||
|
#include "spperif.h"
|
||
|
#include "z80.h"
|
||
|
|
||
|
#include "sptape.h"
|
||
|
#include "snapshot.h"
|
||
|
#include "spsound.h"
|
||
|
#include "spscr.h"
|
||
|
|
||
|
#include "interf.h"
|
||
|
|
||
|
#include <stdlib.h>
|
||
|
#include <stdio.h>
|
||
|
#include <ctype.h>
|
||
|
|
||
|
int keyboard_type = 0;
|
||
|
|
||
|
/* for kempston support via SK_KP_Up and so on.... */
|
||
|
int cursor_type = 2;
|
||
|
|
||
|
|
||
|
int spkb_allow_ascii = 1;
|
||
|
int spkb_trueshift = -1;
|
||
|
int spkb_funcshift = -1;
|
||
|
|
||
|
static unsigned trueshift;
|
||
|
static unsigned funcshift;
|
||
|
|
||
|
struct spkeydef {
|
||
|
int type;
|
||
|
spkeyboard kb;
|
||
|
};
|
||
|
|
||
|
struct spbasekey {
|
||
|
int index;
|
||
|
spkeyboard kb;
|
||
|
spkeyboard misc;
|
||
|
};
|
||
|
|
||
|
struct spnamedkey {
|
||
|
const char *name;
|
||
|
spkeyboard kb;
|
||
|
spkeyboard misc;
|
||
|
};
|
||
|
|
||
|
extern int endofsingle;
|
||
|
extern int sp_nosync;
|
||
|
extern int showframe;
|
||
|
extern int privatemap;
|
||
|
|
||
|
spkeyboard spkey_state;
|
||
|
spkeyboard spmisc_state;
|
||
|
|
||
|
static spkeyboard oldstate = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
||
|
|
||
|
struct keystate spkb_kbstate[NR_SPKEYS];
|
||
|
struct onekey spkb_last;
|
||
|
|
||
|
int spkb_state_changed;
|
||
|
|
||
|
#define SKE {0, 0, 0, 0, 0, 0, 0, 0}
|
||
|
|
||
|
#define SKP(x) (1 << x)
|
||
|
|
||
|
#define SKN0(x) {SKP(x), 0, 0, 0, 0, 0, 0, 0}
|
||
|
#define SKN1(x) {0, SKP(x), 0, 0, 0, 0, 0, 0}
|
||
|
#define SKN2(x) {0, 0, SKP(x), 0, 0, 0, 0, 0}
|
||
|
#define SKN3(x) {0, 0, 0, SKP(x), 0, 0, 0, 0}
|
||
|
#define SKN4(x) {0, 0, 0, 0, SKP(x), 0, 0, 0}
|
||
|
#define SKN5(x) {0, 0, 0, 0, 0, SKP(x), 0, 0}
|
||
|
#define SKN6(x) {0, 0, 0, 0, 0, 0, SKP(x), 0}
|
||
|
#define SKN7(x) {0, 0, 0, 0, 0, 0, 0, SKP(x)}
|
||
|
|
||
|
#define SKCS0(x) {SKP(0) | SKP(x), 0, 0, 0, 0, 0, 0, 0}
|
||
|
#define SKCS1(x) {SKP(0), SKP(x), 0, 0, 0, 0, 0, 0}
|
||
|
#define SKCS2(x) {SKP(0), 0, SKP(x), 0, 0, 0, 0, 0}
|
||
|
#define SKCS3(x) {SKP(0), 0, 0, SKP(x), 0, 0, 0, 0}
|
||
|
#define SKCS4(x) {SKP(0), 0, 0, 0, SKP(x), 0, 0, 0}
|
||
|
#define SKCS5(x) {SKP(0), 0, 0, 0, 0, SKP(x), 0, 0}
|
||
|
#define SKCS6(x) {SKP(0), 0, 0, 0, 0, 0, SKP(x), 0}
|
||
|
#define SKCS7(x) {SKP(0), 0, 0, 0, 0, 0, 0, SKP(x)}
|
||
|
|
||
|
|
||
|
#define SKSS0(x) {SKP(x), 0, 0, 0, 0, 0, 0, SKP(1)}
|
||
|
#define SKSS1(x) {0, SKP(x), 0, 0, 0, 0, 0, SKP(1)}
|
||
|
#define SKSS2(x) {0, 0, SKP(x), 0, 0, 0, 0, SKP(1)}
|
||
|
#define SKSS3(x) {0, 0, 0, SKP(x), 0, 0, 0, SKP(1)}
|
||
|
#define SKSS4(x) {0, 0, 0, 0, SKP(x), 0, 0, SKP(1)}
|
||
|
#define SKSS5(x) {0, 0, 0, 0, 0, SKP(x), 0, SKP(1)}
|
||
|
#define SKSS6(x) {0, 0, 0, 0, 0, 0, SKP(x), SKP(1)}
|
||
|
#define SKSS7(x) {0, 0, 0, 0, 0, 0, 0, SKP(x) | SKP(1)}
|
||
|
|
||
|
|
||
|
#define KEMP(x) {x, 0, 0, 0, 0, 0, 0, 0}
|
||
|
|
||
|
#define KEMPR 0x01
|
||
|
#define KEMPL 0x02
|
||
|
#define KEMPD 0x04
|
||
|
#define KEMPU 0x08
|
||
|
#define KEMPF 0x10
|
||
|
|
||
|
#define KEMP_PORT 0x1F
|
||
|
|
||
|
|
||
|
#define T_MAIN 0
|
||
|
#define T_CMPX 1
|
||
|
#define T_EXTR 2
|
||
|
|
||
|
#define SPK_SPACE SKN7(0)
|
||
|
|
||
|
#define SPK_0 SKN4(0)
|
||
|
#define SPK_1 SKN3(0)
|
||
|
#define SPK_2 SKN3(1)
|
||
|
#define SPK_3 SKN3(2)
|
||
|
#define SPK_4 SKN3(3)
|
||
|
#define SPK_5 SKN3(4)
|
||
|
#define SPK_6 SKN4(4)
|
||
|
#define SPK_7 SKN4(3)
|
||
|
#define SPK_8 SKN4(2)
|
||
|
#define SPK_9 SKN4(1)
|
||
|
|
||
|
#define SPK_A SKN1(0)
|
||
|
#define SPK_B SKN7(4)
|
||
|
#define SPK_C SKN0(3)
|
||
|
#define SPK_D SKN1(2)
|
||
|
#define SPK_E SKN2(2)
|
||
|
#define SPK_F SKN1(3)
|
||
|
#define SPK_G SKN1(4)
|
||
|
#define SPK_H SKN6(4)
|
||
|
#define SPK_I SKN5(2)
|
||
|
#define SPK_J SKN6(3)
|
||
|
#define SPK_K SKN6(2)
|
||
|
#define SPK_L SKN6(1)
|
||
|
#define SPK_M SKN7(2)
|
||
|
#define SPK_N SKN7(3)
|
||
|
#define SPK_O SKN5(1)
|
||
|
#define SPK_P SKN5(0)
|
||
|
#define SPK_Q SKN2(0)
|
||
|
#define SPK_R SKN2(3)
|
||
|
#define SPK_S SKN1(1)
|
||
|
#define SPK_T SKN2(4)
|
||
|
#define SPK_U SKN5(3)
|
||
|
#define SPK_V SKN0(4)
|
||
|
#define SPK_W SKN2(1)
|
||
|
#define SPK_X SKN0(2)
|
||
|
#define SPK_Y SKN5(4)
|
||
|
#define SPK_Z SKN0(1)
|
||
|
|
||
|
#define SPK_ENTER SKN6(0)
|
||
|
#define SPK_CAPSSHIFT SKN0(0)
|
||
|
#define SPK_SYMBOLSHIFT SKN7(1)
|
||
|
|
||
|
#define SPK_BS SKCS4(0)
|
||
|
#define SPK_UP SKCS4(3)
|
||
|
#define SPK_DOWN SKCS4(4)
|
||
|
#define SPK_LEFT SKCS3(4)
|
||
|
#define SPK_RIGHT SKCS4(2)
|
||
|
#define SPK_CAPSLOCK SKCS3(1)
|
||
|
#define SPK_EXTRA SKCS7(1)
|
||
|
#define SPK_EDIT SKCS3(0)
|
||
|
|
||
|
static spkeyboard spk_extra = SPK_EXTRA;
|
||
|
|
||
|
static struct spkeydef spkey_ascii[] = {
|
||
|
{T_MAIN, SPK_SPACE}, /* space */
|
||
|
{T_CMPX, SKSS3(0)}, /* ! */
|
||
|
{T_CMPX, SKSS5(0)}, /* " */
|
||
|
{T_CMPX, SKSS3(2)}, /* # */
|
||
|
{T_CMPX, SKSS3(3)}, /* $ */
|
||
|
{T_CMPX, SKSS3(4)}, /* % */
|
||
|
{T_CMPX, SKSS4(4)}, /* & */
|
||
|
{T_CMPX, SKSS4(3)}, /* ' */
|
||
|
{T_CMPX, SKSS4(2)}, /* ( */
|
||
|
{T_CMPX, SKSS4(1)}, /* ) */
|
||
|
{T_CMPX, SKSS7(4)}, /* * */
|
||
|
{T_CMPX, SKSS6(2)}, /* + */
|
||
|
{T_CMPX, SKSS7(3)}, /* , */
|
||
|
{T_CMPX, SKSS6(3)}, /* - */
|
||
|
{T_CMPX, SKSS7(2)}, /* . */
|
||
|
{T_CMPX, SKSS0(4)}, /* / */
|
||
|
|
||
|
{T_MAIN, SPK_0}, /* 0 */
|
||
|
{T_MAIN, SPK_1}, /* 1 */
|
||
|
{T_MAIN, SPK_2}, /* 2 */
|
||
|
{T_MAIN, SPK_3}, /* 3 */
|
||
|
{T_MAIN, SPK_4}, /* 4 */
|
||
|
{T_MAIN, SPK_5}, /* 5 */
|
||
|
{T_MAIN, SPK_6}, /* 6 */
|
||
|
{T_MAIN, SPK_7}, /* 7 */
|
||
|
{T_MAIN, SPK_8}, /* 8 */
|
||
|
{T_MAIN, SPK_9}, /* 9 */
|
||
|
|
||
|
{T_CMPX, SKSS0(1)}, /* : */
|
||
|
{T_CMPX, SKSS5(1)}, /* ; */
|
||
|
{T_CMPX, SKSS2(3)}, /* < */
|
||
|
{T_CMPX, SKSS6(1)}, /* = */
|
||
|
{T_CMPX, SKSS2(4)}, /* > */
|
||
|
{T_CMPX, SKSS0(3)}, /* ? */
|
||
|
{T_CMPX, SKSS3(1)}, /* @ */
|
||
|
|
||
|
{T_CMPX, SKCS1(0)}, /* A */
|
||
|
{T_CMPX, SKCS7(4)}, /* B */
|
||
|
{T_CMPX, SKCS0(3)}, /* C */
|
||
|
{T_CMPX, SKCS1(2)}, /* D */
|
||
|
{T_CMPX, SKCS2(2)}, /* E */
|
||
|
{T_CMPX, SKCS1(3)}, /* F */
|
||
|
{T_CMPX, SKCS1(4)}, /* G */
|
||
|
{T_CMPX, SKCS6(4)}, /* H */
|
||
|
{T_CMPX, SKCS5(2)}, /* I */
|
||
|
{T_CMPX, SKCS6(3)}, /* J */
|
||
|
{T_CMPX, SKCS6(2)}, /* K */
|
||
|
{T_CMPX, SKCS6(1)}, /* L */
|
||
|
{T_CMPX, SKCS7(2)}, /* M */
|
||
|
{T_CMPX, SKCS7(3)}, /* N */
|
||
|
{T_CMPX, SKCS5(1)}, /* O */
|
||
|
{T_CMPX, SKCS5(0)}, /* P */
|
||
|
{T_CMPX, SKCS2(0)}, /* Q */
|
||
|
{T_CMPX, SKCS2(3)}, /* R */
|
||
|
{T_CMPX, SKCS1(1)}, /* S */
|
||
|
{T_CMPX, SKCS2(4)}, /* T */
|
||
|
{T_CMPX, SKCS5(3)}, /* U */
|
||
|
{T_CMPX, SKCS0(4)}, /* V */
|
||
|
{T_CMPX, SKCS2(1)}, /* W */
|
||
|
{T_CMPX, SKCS0(2)}, /* X */
|
||
|
{T_CMPX, SKCS5(4)}, /* Y */
|
||
|
{T_CMPX, SKCS0(1)}, /* Z */
|
||
|
|
||
|
{T_EXTR, SKCS5(4)}, /* [ */
|
||
|
{T_EXTR, SKCS1(2)}, /* backslash */
|
||
|
{T_EXTR, SKCS5(3)}, /* ] */
|
||
|
{T_CMPX, SKSS6(4)}, /* ^ */
|
||
|
{T_CMPX, SKSS4(0)}, /* _ */
|
||
|
{T_CMPX, SKSS0(2)}, /* ` */
|
||
|
|
||
|
{T_MAIN, SPK_A}, /* a */
|
||
|
{T_MAIN, SPK_B}, /* b */
|
||
|
{T_MAIN, SPK_C}, /* c */
|
||
|
{T_MAIN, SPK_D}, /* d */
|
||
|
{T_MAIN, SPK_E}, /* e */
|
||
|
{T_MAIN, SPK_F}, /* f */
|
||
|
{T_MAIN, SPK_G}, /* g */
|
||
|
{T_MAIN, SPK_H}, /* h */
|
||
|
{T_MAIN, SPK_I}, /* i */
|
||
|
{T_MAIN, SPK_J}, /* j */
|
||
|
{T_MAIN, SPK_K}, /* k */
|
||
|
{T_MAIN, SPK_L}, /* l */
|
||
|
{T_MAIN, SPK_M}, /* m */
|
||
|
{T_MAIN, SPK_N}, /* n */
|
||
|
{T_MAIN, SPK_O}, /* o */
|
||
|
{T_MAIN, SPK_P}, /* p */
|
||
|
{T_MAIN, SPK_Q}, /* q */
|
||
|
{T_MAIN, SPK_R}, /* r */
|
||
|
{T_MAIN, SPK_S}, /* s */
|
||
|
{T_MAIN, SPK_T}, /* t */
|
||
|
{T_MAIN, SPK_U}, /* u */
|
||
|
{T_MAIN, SPK_V}, /* v */
|
||
|
{T_MAIN, SPK_W}, /* w */
|
||
|
{T_MAIN, SPK_X}, /* x */
|
||
|
{T_MAIN, SPK_Y}, /* y */
|
||
|
{T_MAIN, SPK_Z}, /* z */
|
||
|
|
||
|
{T_EXTR, SKCS1(3)}, /* { */
|
||
|
{T_EXTR, SKCS1(1)}, /* | */
|
||
|
{T_EXTR, SKCS1(4)}, /* } */
|
||
|
{T_EXTR, SKCS1(0)}, /* ~ */
|
||
|
};
|
||
|
|
||
|
static struct spnamedkey spkey_misc[] = {
|
||
|
{"none", SKE, SKE},
|
||
|
|
||
|
{"space", SPK_SPACE, SKE},
|
||
|
{"enter", SPK_ENTER, SKE},
|
||
|
{"capsshift", SPK_CAPSSHIFT, SKE},
|
||
|
{"symbolshift", SPK_SYMBOLSHIFT, SKE},
|
||
|
|
||
|
{"kempston_up", SKE, KEMP(KEMPU)},
|
||
|
{"kempston_down", SKE, KEMP(KEMPD)},
|
||
|
{"kempston_left", SKE, KEMP(KEMPL)},
|
||
|
{"kempston_right", SKE, KEMP(KEMPR)},
|
||
|
{"kempston_fire", SKE, KEMP(KEMPF)},
|
||
|
|
||
|
{NULL, SKE, SKE}
|
||
|
};
|
||
|
|
||
|
#define MAXBASEKEYS 128
|
||
|
|
||
|
static struct spbasekey basekeys[MAXBASEKEYS];
|
||
|
static int numbasekeys;
|
||
|
|
||
|
static struct spbasekey customkeys[MAXBASEKEYS];
|
||
|
static int numcustomkeys = 0;
|
||
|
|
||
|
static struct spbasekey normalkeys[] = {
|
||
|
{'0', SPK_0, SKE}, /* 0 */
|
||
|
{'1', SPK_1, SKE}, /* 1 */
|
||
|
{'2', SPK_2, SKE}, /* 2 */
|
||
|
{'3', SPK_3, SKE}, /* 3 */
|
||
|
{'4', SPK_4, SKE}, /* 4 */
|
||
|
{'5', SPK_5, SKE}, /* 5 */
|
||
|
{'6', SPK_6, SKE}, /* 6 */
|
||
|
{'7', SPK_7, SKE}, /* 7 */
|
||
|
{'8', SPK_8, SKE}, /* 8 */
|
||
|
{'9', SPK_9, SKE}, /* 9 */
|
||
|
|
||
|
{'a', SPK_A, SKE}, /* a */
|
||
|
{'b', SPK_B, SKE}, /* b */
|
||
|
{'c', SPK_C, SKE}, /* c */
|
||
|
{'d', SPK_D, SKE}, /* d */
|
||
|
{'e', SPK_E, SKE}, /* e */
|
||
|
{'f', SPK_F, SKE}, /* f */
|
||
|
{'g', SPK_G, SKE}, /* g */
|
||
|
{'h', SPK_H, SKE}, /* h */
|
||
|
{'i', SPK_I, SKE}, /* i */
|
||
|
{'j', SPK_J, SKE}, /* j */
|
||
|
{'k', SPK_K, SKE}, /* k */
|
||
|
{'l', SPK_L, SKE}, /* l */
|
||
|
{'m', SPK_M, SKE}, /* m */
|
||
|
{'n', SPK_N, SKE}, /* n */
|
||
|
{'o', SPK_O, SKE}, /* o */
|
||
|
{'p', SPK_P, SKE}, /* p */
|
||
|
{'q', SPK_Q, SKE}, /* q */
|
||
|
{'r', SPK_R, SKE}, /* r */
|
||
|
{'s', SPK_S, SKE}, /* s */
|
||
|
{'t', SPK_T, SKE}, /* t */
|
||
|
{'u', SPK_U, SKE}, /* u */
|
||
|
{'v', SPK_V, SKE}, /* v */
|
||
|
{'w', SPK_W, SKE}, /* w */
|
||
|
{'x', SPK_X, SKE}, /* x */
|
||
|
{'y', SPK_Y, SKE}, /* y */
|
||
|
{'z', SPK_Z, SKE}, /* z */
|
||
|
|
||
|
{-1, SKE, SKE}
|
||
|
};
|
||
|
|
||
|
static struct spbasekey extendedkeys[] = {
|
||
|
{' ', SPK_SPACE, SKE}, /* space */
|
||
|
{TRKS(SK_Return), SPK_ENTER, SKE}, /* enter */
|
||
|
{TRKS(SK_KP_Enter), SPK_ENTER, SKE},
|
||
|
{TRKS(SK_Shift_L), SPK_CAPSSHIFT, SKE}, /* caps shift */
|
||
|
{TRKS(SK_Shift_R), SPK_SYMBOLSHIFT, SKE}, /* symbol shift */
|
||
|
{TRKS(SK_BackSpace), SPK_BS, SKE}, /* backspace */
|
||
|
{TRKS(SK_Delete), SPK_BS, SKE},
|
||
|
{TRKS(SK_KP_Delete), SPK_BS, SKE},
|
||
|
{TRKS(SK_Escape), SPK_EDIT, SKE}, /* caps shift + '1' */
|
||
|
|
||
|
{-1, SKE, SKE}
|
||
|
};
|
||
|
|
||
|
static struct spbasekey spectrumkeys[] = {
|
||
|
{',', SPK_SYMBOLSHIFT, SKE},
|
||
|
{'.', SPK_SPACE, SKE},
|
||
|
{';', SPK_ENTER, SKE},
|
||
|
|
||
|
{-1, SKE, SKE}
|
||
|
};
|
||
|
|
||
|
|
||
|
static struct spbasekey compatkeys[] = {
|
||
|
{TRKS(SK_Shift_L), SPK_CAPSSHIFT, SKE}, /* caps shift */
|
||
|
{TRKS(SK_Shift_R), SPK_CAPSSHIFT, SKE},
|
||
|
{TRKS(SK_Alt_L), SPK_SYMBOLSHIFT, SKE}, /* symbol shift */
|
||
|
{TRKS(SK_Alt_R), SPK_SYMBOLSHIFT, SKE},
|
||
|
{TRKS(SK_Meta_L), SPK_SYMBOLSHIFT, SKE},
|
||
|
{TRKS(SK_Meta_R), SPK_SYMBOLSHIFT, SKE},
|
||
|
#if TRUEKOMPAT
|
||
|
{TRKS(SK_Control_L), SPK_EXTRA, SKE}, /* caps shift + symbol shift */
|
||
|
{TRKS(SK_Control_R), SPK_EXTRA, SKE},
|
||
|
#endif
|
||
|
|
||
|
{-1, SKE, SKE}
|
||
|
};
|
||
|
|
||
|
static struct spbasekey shiftedcurs[] = {
|
||
|
{TRKS(SK_Up), SPK_UP, SKE}, /* up */
|
||
|
{TRKS(SK_KP_Up), SPK_UP, SKE},
|
||
|
{TRKS(SK_Down), SPK_DOWN, SKE}, /* down */
|
||
|
{TRKS(SK_KP_Down), SPK_DOWN, SKE},
|
||
|
{TRKS(SK_Left), SPK_LEFT, SKE}, /* left */
|
||
|
{TRKS(SK_KP_Left), SPK_LEFT, SKE},
|
||
|
{TRKS(SK_Right), SPK_RIGHT, SKE}, /* right */
|
||
|
{TRKS(SK_KP_Right), SPK_RIGHT, SKE},
|
||
|
|
||
|
{-1, SKE, SKE}
|
||
|
};
|
||
|
|
||
|
static struct spbasekey rawcurs[] = {
|
||
|
{TRKS(SK_Up), SPK_7, SKE}, /* up */
|
||
|
{TRKS(SK_KP_Up), SPK_7, SKE},
|
||
|
{TRKS(SK_Down), SPK_6, SKE}, /* down */
|
||
|
{TRKS(SK_KP_Down), SPK_6, SKE},
|
||
|
{TRKS(SK_Left), SPK_5, SKE}, /* left */
|
||
|
{TRKS(SK_KP_Left), SPK_5, SKE},
|
||
|
{TRKS(SK_Right), SPK_8, SKE}, /* right */
|
||
|
{TRKS(SK_KP_Right), SPK_8, SKE},
|
||
|
|
||
|
{-1, SKE, SKE}
|
||
|
};
|
||
|
|
||
|
static struct spbasekey joycurs[] = {
|
||
|
{TRKS(SK_Up), SKE, KEMP(KEMPU)}, /* up */
|
||
|
{TRKS(SK_KP_Up), SKE, KEMP(KEMPU)},
|
||
|
{TRKS(SK_Down), SKE, KEMP(KEMPD)}, /* down */
|
||
|
{TRKS(SK_KP_Down), SKE, KEMP(KEMPD)},
|
||
|
{TRKS(SK_Left), SKE, KEMP(KEMPL)}, /* left */
|
||
|
{TRKS(SK_KP_Left), SKE, KEMP(KEMPL)},
|
||
|
{TRKS(SK_Right), SKE, KEMP(KEMPR)}, /* right */
|
||
|
{TRKS(SK_KP_Right), SKE, KEMP(KEMPR)},
|
||
|
{TRKS(SK_KP_Insert), SKE, KEMP(KEMPF)}, /* fire */
|
||
|
{TRKS(SK_Insert), SKE, KEMP(KEMPF)},
|
||
|
{TRKS(SK_KP_Delete), SKE, KEMP(KEMPF)},
|
||
|
{TRKS(SK_KP_Home), SKE, KEMP(KEMPU | KEMPL)}, /* up + left*/
|
||
|
{TRKS(SK_Home), SKE, KEMP(KEMPU | KEMPL)},
|
||
|
{TRKS(SK_KP_Page_Up), SKE, KEMP(KEMPU | KEMPR)}, /* up + right*/
|
||
|
{TRKS(SK_Page_Up), SKE, KEMP(KEMPU | KEMPR)},
|
||
|
{TRKS(SK_KP_End), SKE, KEMP(KEMPD | KEMPL)}, /* down + left*/
|
||
|
{TRKS(SK_End), SKE, KEMP(KEMPD | KEMPL)},
|
||
|
{TRKS(SK_KP_Page_Down), SKE, KEMP(KEMPD | KEMPR)}, /* down + right*/
|
||
|
{TRKS(SK_Page_Down), SKE, KEMP(KEMPD | KEMPR)},
|
||
|
|
||
|
{-1, SKE, SKE}
|
||
|
};
|
||
|
|
||
|
int spkey_new_custom(int key)
|
||
|
{
|
||
|
if(numcustomkeys >= MAXBASEKEYS) return 0;
|
||
|
|
||
|
customkeys[numcustomkeys].index = key;
|
||
|
SP_SETEMPTY(customkeys[numcustomkeys].kb);
|
||
|
SP_SETEMPTY(customkeys[numcustomkeys].misc);
|
||
|
numcustomkeys++;
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
int spkey_add_custom(const char *name)
|
||
|
{
|
||
|
int curr;
|
||
|
|
||
|
curr = numcustomkeys - 1;
|
||
|
|
||
|
if(!name[1] && isalnum(name[0])) {
|
||
|
int ai;
|
||
|
ai = tolower(name[0])-32;
|
||
|
SP_COMBINE(customkeys[curr].kb, spkey_ascii[ai].kb);
|
||
|
return 1;
|
||
|
}
|
||
|
else {
|
||
|
int i;
|
||
|
|
||
|
for(i = 0; spkey_misc[i].name != NULL; i++) {
|
||
|
if(mis_strcasecmp(spkey_misc[i].name, name) == 0) {
|
||
|
SP_COMBINE(customkeys[curr].kb, spkey_misc[i].kb);
|
||
|
SP_COMBINE(customkeys[curr].misc, spkey_misc[i].misc);
|
||
|
return 1;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int key_reset(struct keystate *ck)
|
||
|
{
|
||
|
if(ck->state == 2 && sp_int_ctr >= ck->frame) {
|
||
|
ck->state = 0;
|
||
|
return 1;
|
||
|
}
|
||
|
else return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
void process_keys(void)
|
||
|
{
|
||
|
int i;
|
||
|
struct keystate *ck;
|
||
|
int tsh;
|
||
|
int kalone;
|
||
|
static int extrai = 0;
|
||
|
static qbyte extraendframe;
|
||
|
|
||
|
if(extrai && !spkb_kbstate[extrai].state) extrai = 0;
|
||
|
|
||
|
if(!spkb_state_changed && (!extrai || !extraendframe)) return;
|
||
|
|
||
|
SP_SETEMPTY(spkey_state);
|
||
|
SP_SETEMPTY(spmisc_state);
|
||
|
|
||
|
kalone = 0;
|
||
|
ck = spkb_kbstate + spkb_last.index;
|
||
|
tsh = spkb_last.modif & trueshift;
|
||
|
key_reset(ck);
|
||
|
|
||
|
|
||
|
if(spkb_allow_ascii && ck->state && (!ck->base || tsh)) {
|
||
|
unsigned ks;
|
||
|
ks = tsh ? spkb_last.shifted : spkb_last.keysym;
|
||
|
if(ks >= 32 && ks < 127) {
|
||
|
if(spkey_ascii[ks-32].type <= T_CMPX) {
|
||
|
SP_COMBINE(spkey_state, spkey_ascii[ks-32].kb);
|
||
|
kalone = 1;
|
||
|
}
|
||
|
else if(spkey_ascii[ks-32].type == T_EXTR) {
|
||
|
if(!extrai || sp_int_ctr < extraendframe) {
|
||
|
if(!extrai) {
|
||
|
extrai = spkb_last.index;
|
||
|
extraendframe = sp_int_ctr + 1;
|
||
|
}
|
||
|
SP_COMBINE(spkey_state, spk_extra);
|
||
|
}
|
||
|
else {
|
||
|
SP_COMBINE(spkey_state, spkey_ascii[ks-32].kb);
|
||
|
extraendframe = 0;
|
||
|
}
|
||
|
kalone = 1;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(!kalone) {
|
||
|
for(i = 0; i < numbasekeys; i++) {
|
||
|
ck = spkb_kbstate + basekeys[i].index;
|
||
|
key_reset(ck);
|
||
|
if(ck->state) {
|
||
|
SP_COMBINE(spkey_state, basekeys[i].kb);
|
||
|
SP_COMBINE(spmisc_state, basekeys[i].misc);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
SP_COMBINE(spkey_state, kb_mkey);
|
||
|
|
||
|
spkb_refresh();
|
||
|
spkb_state_changed = 0;
|
||
|
}
|
||
|
|
||
|
void clear_keystates(void)
|
||
|
{
|
||
|
int i;
|
||
|
for(i = 0; i < NR_SPKEYS; i++) spkb_kbstate[i].state = 0;
|
||
|
spkb_last.index = 0;
|
||
|
SP_SETEMPTY(spkey_state);
|
||
|
SP_SETEMPTY(kb_mkey);
|
||
|
SP_SETEMPTY(spmisc_state);
|
||
|
spkb_refresh();
|
||
|
}
|
||
|
|
||
|
static void keycpy(struct spbasekey *to, struct spbasekey *from)
|
||
|
{
|
||
|
to->index = from->index;
|
||
|
SP_COPY(to->kb, from->kb);
|
||
|
SP_COPY(to->misc, from->misc);
|
||
|
}
|
||
|
|
||
|
static void copy_key(struct spbasekey *addk)
|
||
|
{
|
||
|
int i;
|
||
|
int nindex;
|
||
|
|
||
|
nindex = addk->index;
|
||
|
|
||
|
if(SP_NONEMPTY(addk->kb) || SP_NONEMPTY(addk->misc)) {
|
||
|
for(i = 0; i < numbasekeys; i++) {
|
||
|
if(basekeys[i].index == nindex) { /* Replace */
|
||
|
keycpy(&basekeys[i], addk);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
if(numbasekeys < MAXBASEKEYS - 1) { /* Add */
|
||
|
keycpy(&basekeys[numbasekeys], addk);
|
||
|
spkb_kbstate[nindex].base = 1;
|
||
|
numbasekeys++;
|
||
|
}
|
||
|
}
|
||
|
else { /* Delete */
|
||
|
for(i = 0; i < numbasekeys; i++) {
|
||
|
if(basekeys[i].index == nindex) {
|
||
|
i++;
|
||
|
for(; i < numbasekeys; i++) keycpy(&basekeys[i-1], &basekeys[i]);
|
||
|
spkb_kbstate[nindex].base = 0;
|
||
|
numbasekeys--;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void copy_basekeys(struct spbasekey *addk)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
for(i = 0; addk[i].index >= 0; i++) copy_key(&addk[i]);
|
||
|
}
|
||
|
|
||
|
static unsigned transform_shift(int modif)
|
||
|
{
|
||
|
if(!modif) return 0;
|
||
|
else return (1 << (modif - 1));
|
||
|
}
|
||
|
|
||
|
|
||
|
void init_basekeys(void)
|
||
|
{
|
||
|
int i;
|
||
|
numbasekeys = 0;
|
||
|
|
||
|
for(i = 0; i < NR_SPKEYS; i++) spkb_kbstate[i].base = 0;
|
||
|
|
||
|
customkeys[numcustomkeys].index = -1;
|
||
|
|
||
|
copy_basekeys(normalkeys);
|
||
|
copy_basekeys(extendedkeys);
|
||
|
copy_basekeys(shiftedcurs);
|
||
|
|
||
|
switch(keyboard_type) {
|
||
|
case 0:
|
||
|
break;
|
||
|
|
||
|
case 1:
|
||
|
copy_basekeys(spectrumkeys);
|
||
|
break;
|
||
|
|
||
|
case 2:
|
||
|
if(spkb_trueshift == -1) spkb_trueshift = 0;
|
||
|
#if TRUEKOMPAT
|
||
|
if(spkb_funcshift == -1) spkb_funcshift = 0;
|
||
|
#endif
|
||
|
|
||
|
copy_basekeys(compatkeys);
|
||
|
break;
|
||
|
|
||
|
case 3:
|
||
|
copy_basekeys(customkeys);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
switch(cursor_type) {
|
||
|
case 0:
|
||
|
break;
|
||
|
|
||
|
case 1:
|
||
|
copy_basekeys(rawcurs);
|
||
|
break;
|
||
|
|
||
|
case 2:
|
||
|
copy_basekeys(joycurs);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if(spkb_trueshift == -1) spkb_trueshift = 4; /* mod1 */
|
||
|
if(spkb_funcshift == -1) spkb_funcshift = 3; /* control */
|
||
|
|
||
|
trueshift = transform_shift(spkb_trueshift);
|
||
|
funcshift = transform_shift(spkb_funcshift);
|
||
|
}
|
||
|
|
||
|
|
||
|
void spkb_refresh(void)
|
||
|
{
|
||
|
int port, pb;
|
||
|
int i, j, changed;
|
||
|
byte *km, *kmo;
|
||
|
byte mm;
|
||
|
byte pv;
|
||
|
spkeyboard statemx;
|
||
|
|
||
|
km = spkey_state;
|
||
|
kmo = oldstate;
|
||
|
changed = 0;
|
||
|
for(i = 8; i; i--) {
|
||
|
if(*km != *kmo) *kmo = *km, changed = 1;
|
||
|
km++, kmo++;
|
||
|
}
|
||
|
|
||
|
if(changed) {
|
||
|
|
||
|
/* Matrix behavior: ONLY 1 level, does anybody need more ? */
|
||
|
|
||
|
for(i = 0; i < 8; i++) {
|
||
|
pv = spkey_state[i];
|
||
|
mm = pv;
|
||
|
if(pv) {
|
||
|
km = spkey_state;
|
||
|
for(j = 8; j; j--) {
|
||
|
if((*km & pv) & 0x1F) mm |= *km;
|
||
|
km++;
|
||
|
}
|
||
|
}
|
||
|
statemx[i] = mm;
|
||
|
}
|
||
|
|
||
|
for(port = 0; port < 256; port++) {
|
||
|
km = statemx;
|
||
|
pv = 0;
|
||
|
pb = port;
|
||
|
for(i = 8; i; i--) {
|
||
|
if(!(pb & 1)) pv |= *km;
|
||
|
pb >>= 1;
|
||
|
km++;
|
||
|
}
|
||
|
sp_fe_inport_high[port] =
|
||
|
(sp_fe_inport_high[port] | 0x1F) & ~(pv & 0x1F);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pv = spmisc_state[0];
|
||
|
|
||
|
if((pv & KEMPR) && (pv & KEMPL)) pv &= ~(KEMPR | KEMPL);
|
||
|
if((pv & KEMPU) && (pv & KEMPD)) pv &= ~(KEMPD | KEMPU);
|
||
|
z80_inports[KEMP_PORT] = pv;
|
||
|
}
|
||
|
|