[comp.sources.atari.st] v02i014: keyfix -- Fix Gulam for non-American keyboards

koreth@ssyx.ucsc.edu (Steven Grimm) (02/25/89)

Submitted-by: uunet!mcvax!cwi.nl!eddy (Eddy Boeve)
Posting-number: Volume 2, Issue 14
Archive-name: keyfix

Here is a program to fix the 'gulam.prg' binary for non-american keyboards.
You do not have to edit the program, just run it. The program does the
rest. The binary is also being posted in comp.binaries.atari.st.

/*
 *	keyfix.c -- Utility for Gulam
 *
 *	Original version: copyright (c) 1986, 1987 pm@cwru.edu
 *
 *	Rewrite 	: eddyright (e) 1989 eddy@cwi.nl
 *
 *	This is an utility for GULAM to patch the default key bindings
 *	in the 'gulam.prg' binary. It was originally created by
 *	'pm@cwru.edu' to change the USA key bindings for us Europeans
 *	and contained a 3*128 table with the desired new bindings.
 *
 *	This version is different because you don't have to edit it for
 *	your own machine. It works out for itself what keys produce what
 *	characters.
 *
 *	This program takes your default key translation tables via the
 *	XBIOS function 'Keytbl' and adds the GULAM function, arrow and
 *	keypad key translations. (Why Gulam doesn't do this is unclear). 
 *	If you already have a USA key binding, everything will stay the 
 *	same. Otherwise the '@~#\|$' keys will hopefully appear under the 
 *	right button. 
 *	
 * 	Compile 'kmpfix.c'.  Run the resulting program from the directory
 *	that contains the 'gulam.prg'.
 *	The new version of 'gulam.prg' (with the new key mapping) will be 
 *	written out as 'gulamnew.prg' in the current directory.
 *
 * 	Below we define ST520/1040 keynames; the values are the ascii codes
 * 	returned by ST BIOS.
 *
 * 	The values below are chosen to have certain patterns:
 *
 *	to SHIFT	  add 0040
 *	F1-10		  0201 to 0212
 *	keypad 0-9	  0260 to 0272 (subtract -0200 to get ascii digits)
 *	keypad()/ *-+.cr  add 0300 to the ascii ()/ *-+.cr
 *
 *	Other choices may be better, I don't know.  However, I think it is
 *	unwise to use numbers in the range 0000 to 0177, because they are
 *	regular ascii codes.
 *
 *	If you want to change some bindings, do it in the routine
 *	'copy_map':
 *		kn['scan_code'] = 'ascii_code';
 *
 *	Exit values:
 *		 0	: No errors,
 *		-1	: Error in finding key map in binary,
 *		-2	: Error in memory allocation,
 *		-3	: Error in file reading/writing.
 */
 
#include <osbind.h>
#include <xbios.h>
#include <bios.h>

#define GULAM_SIZE	(100000L)	/* Number larger than size gulam 
					 * program (in bytes) */

/*
 * 	These 'KC_' scan code values are not defined in <bios.h>
 */
#define	KC_KLP		0x63	/* Keypad (	*/
#define	KC_KRP		0x64	/* Keypad )	*/
#define	KC_KSTAR	0x66	/* Keypad *	*/
#define	KC_KPLUS	0x4E	/* Keypad +	*/
#define	KC_KENT		0x72	/* Keypad Enter	*/
#define	KC_KMINUS	0x4A	/* Keypad -	*/
#define	KC_KDOT		0x71	/* Keypad .	*/
#define	KC_KSLASH	0x65	/* Keypad /	*/
#define	KC_K0		0x70	/* Keypad 0	*/
#define	KC_K1		0x6D	/* Keypad 1	*/
#define	KC_K2		0x6E	/* Keypad 2	*/
#define	KC_K3		0x6F	/* Keypad 3	*/
#define	KC_K4		0x6A	/* Keypad 4	*/
#define	KC_K5		0x6B	/* Keypad 5	*/
#define	KC_K6		0x6C	/* Keypad 6	*/
#define	KC_K7		0x67	/* Keypad 7	*/
#define	KC_K8		0x68	/* Keypad 8	*/
#define	KC_K9		0x69	/* Keypad 9	*/

/*
 *	ST520/1040 keynames
 */
#define F1	0201
#define F2	0202
#define	F3	0203
#define F4	0204
#define F5	0205
#define F6      0206
#define F7	0207
#define F8	0210
#define F9	0211
#define F10	0212

#define HELP    0213
#define UNDO	0214
#define INSERT	0215
#define HOME	0216

#define UPARRO	0273
#define DNARRO	0274
#define LTARRO	0275
#define RTARRO	0276

#define	KLP	0300
#define	KRP	0301
#define	KSTAR	0302
#define	KPLUS	0303
#define	KENTER	0304
#define	KMINUS	0305
#define	KDOT	0306
#define	KSLASH	0307

#define	K0	0260
#define	K1	0261
#define	K2	0262
#define	K3	0263
#define	K4	0264
#define	K5	0265
#define	K6	0266
#define	K7	0267
#define	K8	0270
#define	K9	0271


/* 
 *	The above are the unshifted values.  Shifted, as well as
 *	'capslocked' (for only these keys) values that I use are these +0040.
 */
#define SHIFTED 0040


#define UNSHIFTED_MODE	0	/* Normal (unshifted) mode 	*/
#define SHIFTED_MODE	1	/* With shift key pressed 	*/
#define CAPSLOCK_MODE	2	/* With capslock key pressed 	*/

static
char *mode_string [] = 
	{ 
		"Unshifted Mode", 	/* Mode_string[UNSHIFTED_MODE] 	*/
		"Shifted Mode",  	/* Mode_string[SHIFTED_MODE] 	*/
		"Capslock Mode"  	/* Mode_string[CAPSLOCK_MODE] 	*/
	};

/*
 *	Error ( string, ec)
 *
 *	Write string and exit (ec).
 */
Error (str, ec)
char *str;
int ec;
{
	printf ("Error: ** %s **\n", str);
	exit (ec);

} /* error */

/*
 *	copy_map (mode, k_orig, k_new)
 *
 *	This routine will copy the contents of 'k_orig' (the original
 *	keyboard's translation table for mode 'mode', obtained by the
 *	xbios function 'Keytbl') to the new defined translation table
 *	'k_new'. Also the function/arrow/keypad key entries in 'k_new'
 *	will be changed to the preferred Gulam settings.
 */
void copy_map (mode, k_orig, k_new)
register short  mode;
char	*k_orig,	/* Pointer to original key table for 'mode' */
	*k_new;		/* New defined key table for Gulam */
{
	register char	*ko = k_orig,
			*kn = k_new;
	register int 	i,
		 	offset = 0;	/* If shifted mode, add this */

	printf ("Changing keyboard translation table (%s) at %06lx.\n",
		mode_string[mode], k_orig);

	for (i=0; i<128; i++)
		kn[i] = ko[i];

	/*
	 *	Change Function/Arrow/Keypad keys
	 *	Here you can add/change entries.
         */
	if (mode == SHIFTED_MODE)
		offset = SHIFTED;

	kn[KC_F1]	= F1 + offset;
	kn[KC_F2]	= F2 + offset;
	kn[KC_F3]	= F3 + offset;
	kn[KC_F4]	= F4 + offset;
	kn[KC_F5]	= F5 + offset;
	kn[KC_F6]	= F6 + offset;
	kn[KC_F7]	= F7 + offset;
	kn[KC_F8]	= F8 + offset;
	kn[KC_F9]	= F9 + offset;
	kn[KC_F10]	= F10 + offset;

	kn[KC_HELP]	= HELP + offset;
	kn[KC_UNDO]	= UNDO + offset;
	kn[KC_INS]	= INSERT + offset;
	kn[KC_CLR]	= HOME + offset;

	kn[KC_CUP]	= UPARRO + offset;
	kn[KC_CDOWN]	= DNARRO + offset;
	kn[KC_CLEFT]	= LTARRO + offset;
	kn[KC_CRIGHT]	= RTARRO + offset;

	kn[KC_KLP]	= KLP + offset;
	kn[KC_KRP]	= KRP + offset;
	kn[KC_KSLASH]	= KSLASH + offset;
	kn[KC_KSTAR]	= KSTAR + offset;
	kn[KC_KPLUS] 	= KPLUS + offset;
	kn[KC_KENT]	= KENTER + offset;
	kn[KC_KMINUS]	= KMINUS + offset;
	kn[KC_KDOT]	= KDOT + offset;
	kn[KC_K0]	= K0 + offset;
	kn[KC_K1]	= K1 + offset;
	kn[KC_K2]	= K2 + offset;
	kn[KC_K3]	= K3 + offset;
	kn[KC_K4]	= K4 + offset;
	kn[KC_K5]	= K5 + offset;
	kn[KC_K6]	= K6 + offset;
	kn[KC_K7]	= K7 + offset;
	kn[KC_K8]	= K8 + offset;
	kn[KC_K9]	= K9 + offset;

} /* copy_map */


/* 
 *	Return offset in the binary file gulam.prg where the keymap[] begins.
 *      80336 (decimal) is this number valid for beta-version 
 *	1.03.04.05 (121887).
 */

char * kmpbgn(buf, n)
register char	*buf;
register long	n;
{
	/* kmp[] is extracted from Gulam's src; do NOT change it. */
	static char	kmp[16] = {
		/* -------scan codes: 0x00-0x0f --------------- */
		'\000' /*nul*/, '\033' /*esc*/, 	
		'1' , 	'2' , 	'3' , '4' ,	'5' , 	'6' ,
		'7' , 	'8' , 	'9' , '0' ,	'-' , 	'=' ,
		'\010' /* bs*/, '\011' /* ht*/
	};

	register long	i;
	register int	j;
	register char	*p, *q;

	for (i = 0L; i < n; i++)
	{	p = &buf[i]; q = kmp;
		for (j = 0; j < 16; j++)
			if (*p++ != *q++) break;
		if (j == 16) goto found;
	}
	Error ("key map begin not found!", -1);

	found:	printf("Key map begins at byte %ld\r\n", i);
	return	&buf[i];
}


main()
{
	struct keytbl	*kp;
	register char	*buf, *q;
	register int	i;
	register long	n, m;
	register unsigned long lsz;

	lsz  = GULAM_SIZE;		/* Enough space to hold entire 
					 * gulam.prg! */

	buf = (char *) Malloc(lsz);	
	    if (buf == 0L) 
		Error ("can't Malloc", -2);

	/* read all of gulam.prg into buf */
	i = Fopen("gulam.prg", 0);
	    if (i <= 0) 
		Error ("gulam.prg not found", -3);
	n =  Fread(i, lsz, buf);	
	    if (n <= 0L) 
		Error ("error reading file", -3);
	    else
		if (n == GULAM_SIZE)
		    Error ("gulam.prg probably bigger", -3);
        Fclose(i);

	/*
	 *	Get the keymap beginning in 'gulam.prg'
	 */
	q = kmpbgn(buf, n);

	/* 
	 * 	Fix the keymap tables
	 */
	kp = Keytbl (-1L,-1L,-1L);		/* Get keytable structure */
	copy_map (UNSHIFTED_MODE, kp->kt_normal,   (char *) q );
	copy_map (SHIFTED_MODE,   kp->kt_shifted,  (char *) (q + 128) );
	copy_map (CAPSLOCK_MODE,  kp->kt_capslock, (char *) (q + 256) );

	/* write the new gulam.prg out */
	i = Fcreate("gulamnew.prg", 0);
	    if (i <= 0)
		Error ("could not create gulamnew.prg", -3);

	m =  Fwrite(i, n, buf);	
	    if (m != n) 
		Error ("error writing file", -3);
        Fclose(i);

	printf("new version of gulam is gulamnew.prg\n\n");	

} /* main */