/*
 * Keyboard maps.  This is character set dependent. The terminal specific
 * parts of building the keymap has been moved to a better place. 
 */
#include	"no_dir.h"
#include	"no_dired.h"
#include	"no_backup.h"
#include	"no_help.h"
#include	"no_macro.h"
#include	"no_metakey.h"
#include	"do_eval.h"
#include	"gosmacs.h"
#include	"regexp.h"
#include	"bsmap.h"
#include	"notab.h"
#include	"prefixregion.h"
#undef		AMIGA
#include	"system.h"

#ifdef		AMIGA
#include	"do_menu.h"
#include	"do_iconify.h"
#include	"mouse.h"
#include	"change_font.h"
#include	"change_color.h"
#include	"rexx.h"
#endif

#include	"def.h"
#include	"kbd.h"

#ifdef	ANSI
#include <string.h>
#endif

/*
 * My one little static function. 
 */
static          name_fent
PROTO((char *fname, int flag));

/*
 * Defined by "basic.c". 
 */
extern int      gotobol();	/* Move to start of line	 */
extern int      backchar();	/* Move backward by characters	 */
extern int      gotoeol();	/* Move to end of line		 */
extern int      forwchar();	/* Move forward by characters	 */
extern int      gotobob();	/* Move to start of buffer	 */
extern int      gotoeob();	/* Move to end of buffer	 */
extern int      forwline();	/* Move forward by lines	 */
extern int      backline();	/* Move backward by lines	 */
extern int      forwpage();	/* Move forward by pages	 */
extern int      backpage();	/* Move backward by pages	 */
extern int      pagenext();	/* Page forward next window	 */
extern int      setmark();	/* Set mark			 */
extern int      swapmark();	/* Swap "." and mark		 */
extern int      gotoline();	/* Go to a specified line.	 */
#ifdef	GOSMACS
extern int      forw1page();	/* move forward by lines	 */
extern int      back1page();	/* move back by lines		 */
#endif

/*
 * Defined by "buffer.c". 
 */
extern int      listbuffers();	/* Display list of buffers	 */
extern int      usebuffer();	/* Switch a window to a buffer	 */
extern int      poptobuffer();	/* Other window to a buffer	 */
extern int      killbuffer();	/* Make a buffer go away.	 */
extern int      savebuffers();	/* Save unmodified buffers	 */
extern int      bufferinsert();	/* Insert buffer into another	 */
extern int      notmodified();	/* Reset modification flag	 */

#ifndef NO_DIR
/*
 * Defined by "dir.c" 
 */
extern int      changedir();	/* change current directory	 */
extern int      showcwdir();	/* show current directory	 */

#ifndef NO_DIRED
/*
 * defined by "dired.c" 
 */
extern int      dired();	/* dired			 */
extern int      d_findfile();	/* dired find file		 */
extern int      d_del();	/* dired mark for deletion	 */
extern int      d_undel();	/* dired unmark			 */
extern int      d_undelbak();	/* dired unmark backwards	 */
extern int      d_expunge();	/* dired expunge		 */
extern int      d_copy();	/* dired copy			 */
extern int      d_rename();	/* dired rename			 */
extern int      d_otherwindow();/* dired other window		 */
extern int      d_ffotherwindow();	/* dired find file other window */
#endif
#endif

/*
 * Defined by "extend.c". 
 */
extern int      extend();	/* Extended commands.		 */
extern int      bindtokey();	/* Modify global key bindings.	 */
#ifdef DO_EVAL
extern int      evalexpr();	/* Extended commands (again)	 */
extern int      evalbuffer();	/* Evaluate current buffer	 */
extern int      evalfile();	/* Evaluate a file		 */
#endif


/*
 * Defined by "bind.c". 
 */
extern int      localbind();	/* Modify mode key bindings.	 */
extern int      unbindtokey();	/* delete global binding	 */
extern int      localunbind();	/* delete local binding		 */
extern int      define_key();	/* Modify key in any map	 */

/*
 * Defined by "file.c". 
 */
extern int      filevisit();	/* Get a file, read write	 */
extern int      poptofile();	/* Get a file, other window	 */
extern int      filewrite();	/* Write a file			 */
extern int      filesave();	/* Save current file		 */
extern int      fileinsert();	/* Insert file into buffer	 */
extern int      revertbuffer();	/* revert buffer from file	 */
#ifndef NO_BACKUP
extern int      makebkfile();	/* Control backups on saves	 */
#endif

/*
 * defined by help.c 
 */
#ifndef NO_HELP
extern int      desckey();	/* describe key			 */
extern int      wallchart();	/* Make wall chart.		 */
extern int      help_help();	/* help help			 */
extern int      apropos_command();	/* apropos			 */
#endif

/*
 * defined by "kbd.c" 
 */
#ifndef	NO_METAKEY
extern int      do_meta();	/* interpret meta keys		 */
#endif
#ifdef	BSMAP
extern int      bsmap();	/* backspace mapping		 */
#endif
extern int      universal_argument();	/* Ctrl-U			 */
extern int      digit_argument();	/* M-1, etc.			 */
extern int      negative_argument();	/* M--				 */
extern int      selfinsert();	/* Insert character		 */
extern int      rescan();	/* internal try again function	 */

/*
 * defined by "macro.c" 
 */
#ifndef NO_MACRO
extern int      definemacro();	/* Begin macro			 */
extern int      finishmacro();	/* End macro			 */
extern int      executemacro();	/* Execute macro		 */
extern int      insertmacro();	/* Insert macro definition	 */
extern int      namemacro();	/* Name keyboard macro		 */
extern int      macroquery();	/* Query user during kbd macro	 */
extern int      macroset();	/* evalable macro definer	 */
#endif

/*
 * Defined by "main.c". 
 */
extern int      ctrlg();	/* Abort out of things		 */
extern int      quit();		/* Quit				 */

/*
 * Defined by "match.c" 
 */
extern int      showmatch();	/* Hack to show matching paren	 */

/* defined by "modes.c" */

extern int      indentmode();	/* set auto-indent mode		 */
extern int      fillmode();	/* set word-wrap mode		 */
extern int      blinkparen();	/* Fake blink-matching-paren var */
#ifdef	NOTAB
extern int      notabmode();	/* no tab mode			 */
#endif
extern int      overwrite();	/* overwrite mode		 */
extern int      set_default_mode();	/* set default modes		 */

/*
 * defined by "paragraph.c" - the paragraph justification code. 
 */
extern int      gotobop();	/* Move to start of paragraph.	 */
extern int      gotoeop();	/* Move to end of paragraph.	 */
extern int      fillpara();	/* Justify a paragraph.		 */
extern int      killpara();	/* Delete a paragraph.		 */
extern int      setfillcol();	/* Set fill column for justify. */
extern int      fillword();	/* Insert char with word wrap.	 */

/*
 * Defined by "random.c". 
 */
extern int      showcpos();	/* Show the cursor position	 */
extern int      twiddle();	/* Twiddle characters		 */
extern int      quote();	/* Insert literal		 */
extern int      openline();	/* Open up a blank line		 */
extern int      newline();	/* Insert newline		 */
extern int      deblank();	/* Delete blank lines		 */
extern int      justone();	/* Delete extra whitespace	 */
extern int      delwhite();	/* Delete all whitespace	 */
extern int      indent();	/* Insert newline, then indent	 */
extern int      forwdel();	/* Forward delete		 */
extern int      backdel();	/* Backward delete in		 */
extern int      killline();	/* Kill forward			 */
extern int      yank();		/* Yank back from killbuffer.	 */
#ifdef NOTAB
extern int      space_to_tabstop();
#endif

#ifdef	REGEXP
/*
 * Defined by "re_search.c" 
 */
extern int      re_forwsearch();/* Regex search forward		 */
extern int      re_backsearch();/* Regex search backwards	 */
extern int      re_searchagain();	/* Repeat regex search command	 */
extern int      re_queryrepl();	/* Regex query replace		 */
extern int      setcasefold();	/* Set case fold in searches	 */
extern int      delmatchlines();/* Delete all lines matching	 */
extern int      delnonmatchlines();	/* Delete all lines not matching */
extern int      cntmatchlines();/* Count matching lines		 */
extern int      cntnonmatchlines();	/* Count nonmatching lines	 */
#endif

/*
 * Defined by "region.c". 
 */
extern int      killregion();	/* Kill region.			 */
extern int      copyregion();	/* Copy region to kill buffer.	 */
extern int      lowerregion();	/* Lower case region.		 */
extern int      upperregion();	/* Upper case region.		 */
#ifdef	PREFIXREGION
extern int      prefixregion();	/* Prefix all lines in region	 */
extern int      setprefix();	/* Set line prefix string	 */
#endif

/*
 * Defined by "search.c". 
 */
extern int      forwsearch();	/* Search forward		 */
extern int      backsearch();	/* Search backwards		 */
extern int      searchagain();	/* Repeat last search command	 */
extern int      forwisearch();	/* Incremental search forward	 */
extern int      backisearch();	/* Incremental search backwards */
extern int      queryrepl();	/* Query replace		 */

/*
 * Defined by "spawn.c". 
 */
extern int      spawncli();	/* Run CLI in a subjob.		 */
#ifdef	VMS
extern int      attachtoparent();	/* Attach to parent process	 */
#endif

/* defined by "version.c" */

extern int      showversion();	/* Show version numbers, etc.	 */

/*
 * Defined by "window.c". 
 */
extern int      reposition();	/* Reposition window		 */
extern int      refresh();	/* Refresh the screen		 */
extern int      nextwind();	/* Move to the next window	 */
#ifdef	GOSMACS
extern int      prevwind();	/* Move to the previous window	 */
#endif
extern int      onlywind();	/* Make current window only one */
extern int      splitwind();	/* Split current window		 */
extern int      delwind();	/* Delete current window	 */
extern int      enlargewind();	/* Enlarge display window.	 */
extern int      shrinkwind();	/* Shrink window.		 */

/*
 * Defined by "word.c". 
 */
extern int      backword();	/* Backup by words		 */
extern int      forwword();	/* Advance by words		 */
extern int      upperword();	/* Upper case word.		 */
extern int      lowerword();	/* Lower case word.		 */
extern int      capword();	/* Initial capitalize word.	 */
extern int      delfword();	/* Delete forward word.		 */
extern int      delbword();	/* Delete backward word.	 */

#ifdef	AMIGA
#ifdef	DO_ICONIFY
extern int      tticon();
#endif
#ifdef	DO_MENU
extern int      amigamenu();	/* Menu function		 */
#endif
#ifdef	MOUSE
extern int      amigamouse();	/* Amiga mouse functions	 */
extern int      mgotobob();
extern int      mforwdel();
extern int      mdelwhite();
extern int      mdelwind();
extern int      mgotoeob();
extern int      menlargewind();
extern int      mkillline();
extern int      mkillregion();
extern int      mdelfword();
extern int      mreposition();
extern int      mbackpage();
extern int      mforwpage();
extern int      mshrinkwind();
extern int      msplitwind();
extern int      myank();
#endif

extern int      togglewindow();	/* Defined by "ttyio.c"		 */
extern int      togglezooms();	/* ""         ""		 */

#ifdef	CHANGE_FONT
extern int      setfont();	/* Defined by "ttyio.c"		 */
#endif

#ifdef	CHANGE_COLOR
/* functions to mess with the mode line rendition, window colors */
extern int      ttmode();	/* Defined by "tty.c"		 */
extern int      tttext();	/* ""				 */
extern int      textforeground();	/* ""				 */
extern int      textbackground();	/* ""				 */
extern int      modeforeground();	/* ""				 */
extern int      modebackground();	/* ""				 */
#endif

#ifdef	REXX
/*
 * Defined by "rexx.c". 
 */
extern int      rexxcommand();	/* Issue REXX command */
extern int	rexxexitcommand();/* */ 
extern int      rexxbuffer();	/* return buffer data */
extern int      rexxbuflist();	/* return buffer list */
extern int	rexxregion();	/* */
extern int      rexxdisplay();	/* display a string in echo area */
extern int      rexxinsert();	/* insert text into buffer */
extern int      rexxline();	/* return line */
extern int      rexxcomregion();/* execute region */
extern int      rexxmark();	/* return mark data */
extern int      rexxpoint();	/* return point data */
extern int      rexxrequest();	/* request string from user */
extern int      rexxreqbuf();	/* request buffer name from user */
extern int      rexxreqfunc();	/* request function name from user */
extern int	rexxreqmacro();	/* */
extern int      rexxwindow();	/* return window data */
extern int      rexxlock();	/* Lock to this rexx macro */
extern int      rexxunlock();	/* Unlock current rexx macro */
extern int      rexxwait();	/* Vanish the window and wait for rexx */
extern int      rexxtopwindow();/* Pop the window to the top of it's screen */
#endif

/*
 * This file contains map segment definitions for adding function keys to
 * keymap declarations.  Currently you can add things to the fundamental mode
 * keymap and the dired mode keymap.  See the declaration of diredmap and
 * fundmap for details. 
 */
#include "amiga_maps.h"

#endif				/* AMIGA */

/* initial keymap declarations, deepest first */

/*
 * But first, the two struct functions that are the default for all cases.
 * (NB - the keymap code just flat needs to be rewritten. It is both arcane,
 * and profligate of space). 
 */

static struct function rescan_default = {rescan, F_CFUNCT};
static struct function selfinsert_default = {selfinsert, F_CFUNCT};

#ifndef NO_HELP
static struct function cHcG[] = {
				 {ctrlg, F_CFUNCT},	/* ^G */
				 {help_help, F_CFUNCT},	/* ^H */
};
static struct function cHa[] = {
				{apropos_command, F_CFUNCT},	/* a */
				{wallchart, F_CFUNCT},	/* b */
				{desckey, F_CFUNCT},	/* c */
};
static struct KEYMAPE (2 + IMAPEXT) helpmap = {
	                2,
	                2 + IMAPEXT,
	               &rescan_default,
	{
		{
			                CCHR('G'), CCHR('H'), cHcG
		}              ,
		{
			                'a', 'c', cHa
		}              ,
	}
};
#endif

static struct function cX4cF[] = {
				  {poptofile, F_CFUNCT},	/* ^f */
				  {ctrlg, F_CFUNCT},	/* ^g */
};
static struct function cX4b[] = {
				 {poptobuffer, F_CFUNCT},	/* b */
				 {rescan, F_CFUNCT},	/* c */
				 {rescan, F_CFUNCT},	/* d */
				 {rescan, F_CFUNCT},	/* e */
				 {poptofile, F_CFUNCT},	/* f */
};
static struct KEYMAPE (2 + IMAPEXT) cX4map = {
	                2,
	                2 + IMAPEXT,
	               &rescan_default,
	{
		{
			                CCHR('F'), CCHR('G'), cX4cF
		}              ,
		{
			                'b', 'f', cX4b
		}              ,
	}
};

static struct function cXcB[] = {
				 {listbuffers, F_CFUNCT},	/* ^B */
				 {quit, F_CFUNCT},	/* ^C */
				 {rescan, F_CFUNCT},	/* ^D */
				 {rescan, F_CFUNCT},	/* ^E */
				 {filevisit, F_CFUNCT},	/* ^F */
				 {ctrlg, F_CFUNCT},	/* ^G */
};
static struct function cXcL[] = {
				 {lowerregion, F_CFUNCT},	/* ^L */
				 {rescan, F_CFUNCT},	/* ^M */
				 {rescan, F_CFUNCT},	/* ^N */
				 {deblank, F_CFUNCT},	/* ^O */
				 {rescan, F_CFUNCT},	/* ^P */
				 {rescan, F_CFUNCT},	/* ^Q */
				 {rescan, F_CFUNCT},	/* ^R */
				 {filesave, F_CFUNCT},	/* ^S */
				 {rescan, F_CFUNCT},	/* ^T */
				 {upperregion, F_CFUNCT},	/* ^U */
				 {rescan, F_CFUNCT},	/* ^V */
				 {filewrite, F_CFUNCT},	/* ^W */
				 {swapmark, F_CFUNCT},	/* ^X */
};
#ifndef NO_MACRO
static struct function cXlp[] = {
				 {definemacro, F_CFUNCT},	/* ( */
				 {finishmacro, F_CFUNCT},	/* ) */
};
#endif
static struct function cX0[] = {
				{delwind, F_CFUNCT},	/* 0 */
				{onlywind, F_CFUNCT},	/* 1 */
				{splitwind, F_CFUNCT},	/* 2 */
				{rescan, F_CFUNCT},	/* 3 */
				{(
				  int (*) ()) &cX4map, F_PREFIX},	/* 4 */
};
static struct function cXeq[] = {
				 {showcpos, F_CFUNCT},	/* = */
};
static struct function cXcar[] = {
				  {enlargewind, F_CFUNCT},	/* ^ */
				  {rescan, F_CFUNCT},	/* _ */
				  {rescan, F_CFUNCT},	/* ` */
				  {rescan, F_CFUNCT},	/* a */
				  {usebuffer, F_CFUNCT},	/* b */
				  {rescan, F_CFUNCT},	/* c */
#ifndef NO_DIRED
				  {dired, F_CFUNCT},	/* d */
#else
				  {rescan, F_CFUNCT},	/* d */
#endif
#ifndef NO_MACRO
				  {executemacro, F_CFUNCT},	/* e */
#else
				  {rescan, F_CFUNCT},	/* e */
#endif
				  {setfillcol, F_CFUNCT},	/* f */
				  {rescan, F_CFUNCT},	/* g */
				  {rescan, F_CFUNCT},	/* h */
				  {fileinsert, F_CFUNCT},	/* i */
				  {rescan, F_CFUNCT},	/* j */
				  {killbuffer, F_CFUNCT},	/* k */
				  {rescan, F_CFUNCT},	/* l */
				  {rescan, F_CFUNCT},	/* m */
#ifdef	GOSMACS
				  {nextwind, F_CFUNCT},	/* n */
#else
				  {rescan, F_CFUNCT},	/* n */
#endif
				  {nextwind, F_CFUNCT},	/* o */
#ifdef	GOSMACS
				  {prevwind, F_CFUNCT},	/* p */
#else
				  {rescan, F_CFUNCT},	/* p */
#endif
#ifndef	NO_MACRO
				  {macroquery, F_CFUNCT},	/* q */
#else
				  {rescan, F_CFUNCT},	/* q */
#endif
				  {rescan, F_CFUNCT},	/* r */
				  {savebuffers, F_CFUNCT},	/* s */
};
#ifndef NO_MACRO
static struct KEYMAPE (6 + IMAPEXT) cXmap = {
	                6,
	                6 + IMAPEXT,
#else
static struct KEYMAPE (5 + IMAPEXT) cXmap = {
	                5,
	                5 + IMAPEXT,
#endif
	               &rescan_default,
	{
		{
			                CCHR('B'), CCHR('G'), cXcB
		}              ,
		{
			                CCHR('L'), CCHR('X'), cXcL
		}              ,
#ifndef NO_MACRO
		{
			                '(', ')', cXlp
		}              ,
#endif
		{
			                '0', '4', cX0
		}              ,
		{
			                '=', '=', cXeq
		}              ,
		{
			                '^', 's', cXcar
		}              ,
	}
};

static struct function metacG[] = {
				   {ctrlg, F_CFUNCT},	/* ^G */
};
static struct function metacV[] = {
				   {pagenext, F_CFUNCT},	/* ^V */
};
static struct function metasp[] = {
				   {justone, F_CFUNCT},	/* space */
};
static struct function metapct[] = {
				    {queryrepl, F_CFUNCT},	/* % */
};
static struct function metami[] = {
				   {negative_argument, F_CFUNCT},	/* - */
				   {rescan, F_CFUNCT},	/* . */
				   {rescan, F_CFUNCT},	/* / */
				   {digit_argument, F_CFUNCT},	/* 0 */
				   {digit_argument, F_CFUNCT},	/* 1 */
				   {digit_argument, F_CFUNCT},	/* 2 */
				   {digit_argument, F_CFUNCT},	/* 3 */
				   {digit_argument, F_CFUNCT},	/* 4 */
				   {digit_argument, F_CFUNCT},	/* 5 */
				   {digit_argument, F_CFUNCT},	/* 6 */
				   {digit_argument, F_CFUNCT},	/* 7 */
				   {digit_argument, F_CFUNCT},	/* 8 */
				   {digit_argument, F_CFUNCT},	/* 9 */
				   {rescan, F_CFUNCT},	/* : */
				   {rescan, F_CFUNCT},	/* ; */
				   {gotobob, F_CFUNCT},	/* < */
				   {rescan, F_CFUNCT},	/* = */
				   {gotoeob, F_CFUNCT},	/* > */
};
static struct function metalb[] = {
				   {gotobop, F_CFUNCT},	/* [ */
				   {delwhite, F_CFUNCT},	/* \ */
				   {gotoeop, F_CFUNCT},	/* ] */
				   {rescan, F_CFUNCT},	/* ^ */
				   {rescan, F_CFUNCT},	/* _ */
				   {rescan, F_CFUNCT},	/* ` */
				   {rescan, F_CFUNCT},	/* a */
				   {backword, F_CFUNCT},	/* b */
				   {capword, F_CFUNCT},	/* c */
				   {delfword, F_CFUNCT},	/* d */
				   {rescan, F_CFUNCT},	/* e */
				   {forwword, F_CFUNCT},	/* f */
};
static struct function metal[] = {
				  {lowerword, F_CFUNCT},	/* l */
				  {rescan, F_CFUNCT},	/* m */
				  {rescan, F_CFUNCT},	/* n */
				  {rescan, F_CFUNCT},	/* o */
				  {rescan, F_CFUNCT},	/* p */
				  {fillpara, F_CFUNCT},	/* q */
				  {backsearch, F_CFUNCT},	/* r */
				  {forwsearch, F_CFUNCT},	/* s */
				  {rescan, F_CFUNCT},	/* t */
				  {upperword, F_CFUNCT},	/* u */
				  {backpage, F_CFUNCT},	/* v */
				  {copyregion, F_CFUNCT},	/* w */
				  {extend, F_CFUNCT},	/* x */
};
static struct function metatilde[] = {
				      {notmodified, F_CFUNCT},	/* ~ */
				      {delbword, F_CFUNCT},	/* DEL */
};
static struct KEYMAPE (8 + IMAPEXT) metamap = {
	                8,
	                8 + IMAPEXT,
	               &rescan_default,
	{
		{
			                CCHR('G'), CCHR('G'), metacG
		}              ,
		{
			                CCHR('V'), CCHR('V'), metacV
		}              ,
		{
			                ' ', ' ', metasp
		}              ,
		{
			                '%', '%', metapct
		}              ,
		{
			                '-', '>', metami
		}              ,
		{
			                '[', 'f', metalb
		}              ,
		{
			                'l', 'x', metal
		}              ,
		{
			                '~', CCHR('?'), metatilde
		}              ,
	}
};

static struct function fund_at[] = {
				    {setmark, F_CFUNCT},	/* ^@ */
				    {gotobol, F_CFUNCT},	/* ^A */
				    {backchar, F_CFUNCT},	/* ^B */
				    {rescan, F_CFUNCT},	/* ^C */
				    {forwdel, F_CFUNCT},	/* ^D */
				    {gotoeol, F_CFUNCT},	/* ^E */
				    {forwchar, F_CFUNCT},	/* ^F */
				    {ctrlg, F_CFUNCT},	/* ^G */
#ifndef NO_HELP
				    {(
				      int (*) ()) &helpmap, F_PREFIX},	/* ^H */
#else
				    {rescan, F_CFUNCT},	/* ^H */
#endif
				    {selfinsert, F_CFUNCT},	/* ^I */
				    {indent, F_CFUNCT},	/* ^J */
				    {killline, F_CFUNCT},	/* ^K */
				    {reposition, F_CFUNCT},	/* ^L */
				    {newline, F_CFUNCT},	/* ^M */
				    {forwline, F_CFUNCT},	/* ^N */
				    {openline, F_CFUNCT},	/* ^O */
				    {backline, F_CFUNCT},	/* ^P */
				    {quote, F_CFUNCT},	/* ^Q */
				    {backisearch, F_CFUNCT},	/* ^R */
				    {forwisearch, F_CFUNCT},	/* ^S */
				    {twiddle, F_CFUNCT},	/* ^T */
				    {universal_argument, F_CFUNCT},	/* ^U */
				    {forwpage, F_CFUNCT},	/* ^V */
				    {killregion, F_CFUNCT},	/* ^W */
				    {(int (*) ()) &cXmap, F_PREFIX},	/* ^X */
				    {yank, F_CFUNCT},	/* ^Y */
#ifndef VMS
				    {spawncli, F_CFUNCT},	/* ^Z */
#else
				    {attachtoparent, F_CFUNCT},	/* ^Z */
#endif
				    {(int (*) ()) &metamap, F_PREFIX},	/* esc */
};
static struct function fund_del[] = {
				     {backdel, F_CFUNCT},	/* DEL */
};

#ifndef	FUND_XMAPS
#define NFUND_XMAPS	0	/* extra map sections after normal ones */
#endif

static struct KEYMAPE (2 + NFUND_XMAPS + IMAPEXT) fundmap = {
	                2 + NFUND_XMAPS,
	                2 + NFUND_XMAPS + IMAPEXT,
	               &selfinsert_default,
	{
		{
			                CCHR('@'), CCHR('['), fund_at
		}              ,
		{
			                CCHR('?'), CCHR('?'), fund_del
		}              ,
#ifdef	FUND_XMAPS
		                FUND_XMAPS,
#endif
	}
};

static struct function fill_sp[] = {
				    {fillword, F_CFUNCT},	/* ' ' */
};
static struct KEYMAPE (1 + IMAPEXT) fillmap = {
	                1,
	                1 + IMAPEXT,
	               &rescan_default,
	{
		{
			                ' ', ' ', fill_sp
		}              ,
	}
};

static struct function indent_lf[] = {
				      {newline, F_CFUNCT},	/* ^J */
				      {rescan, F_CFUNCT},	/* ^K */
				      {rescan, F_CFUNCT},	/* ^L */
				      {indent, F_CFUNCT},	/* ^M */
};
static struct KEYMAPE (1 + IMAPEXT) indntmap = {
	                1,
	                1 + IMAPEXT,
	               &rescan_default,
	{
		{
			                CCHR('J'), CCHR('M'), indent_lf
		}              ,
	}
};
static struct function blink_rp[] = {
				     {showmatch, F_CFUNCT},	/* ) */
};
static struct KEYMAPE (1 + IMAPEXT) blinkmap = {
	                1,
	                1 + IMAPEXT,
	               &rescan_default,
	{
		{
			                ')', ')', blink_rp
		}              ,
	}
};

#ifdef	NOTAB
static struct function notab_tab[] = {
				      {space_to_tabstop, F_CFUNCT},	/* ^I */
};
static struct KEYMAPE (1 + IMAPEXT) notabmap = {
	                1,
	                1 + IMAPEXT,
	               &rescan_default,
	{
		{
			                CCHR('I'), CCHR('I'), notab_tab
		}              ,
	}
};
#endif

static struct KEYMAPE (1 + IMAPEXT) overwmap = {
	                0,
	                1 + IMAPEXT,	/* 1 to avoid 0 sized array */
	               &rescan_default,
	{
		/* unused dummy entry for VMS C */
		{
			                (KCHAR) 0, (KCHAR) 0, NULL
		}              ,
	}
};

#ifndef NO_DIRED
static struct function dirednul[] = {
				     {setmark, F_CFUNCT},	/* ^@ */
				     {gotobol, F_CFUNCT},	/* ^A */
				     {backchar, F_CFUNCT},	/* ^B */
				     {rescan, F_CFUNCT},	/* ^C */
				     {d_del, F_CFUNCT},	/* ^D */
				     {gotoeol, F_CFUNCT},	/* ^E */
				     {forwchar, F_CFUNCT},	/* ^F */
				     {ctrlg, F_CFUNCT},	/* ^G */
#ifndef NO_HELP
				     {(
				       int (*) ()) &helpmap, F_PREFIX},	/* ^H */
#endif
};
static struct function diredcl[] = {
				    {reposition, F_CFUNCT},	/* ^L */
				    {forwline, F_CFUNCT},	/* ^M */
				    {forwline, F_CFUNCT},	/* ^N */
				    {rescan, F_CFUNCT},	/* ^O */
				    {backline, F_CFUNCT},	/* ^P */
				    {rescan, F_CFUNCT},	/* ^Q */
				    {backisearch, F_CFUNCT},	/* ^R */
				    {forwisearch, F_CFUNCT},	/* ^S */
				    {rescan, F_CFUNCT},	/* ^T */
				    {universal_argument, F_CFUNCT},	/* ^U */
				    {forwpage, F_CFUNCT},	/* ^V */
				    {rescan, F_CFUNCT},	/* ^W */
				    {(
				      int (*) ()) &cXmap, F_PREFIX},	/* ^X */
};
static struct function diredcz[] = {
#ifndef VMS
				    {spawncli, F_CFUNCT},	/* ^Z */
#else
				    {attachtoparent, F_CFUNCT},	/* ^Z */
#endif
				    {(
				      int (*) ()) &metamap, F_PREFIX},	/* esc */
				    {rescan, F_CFUNCT},	/* ^\ */
				    {rescan, F_CFUNCT},	/* ^] */
				    {rescan, F_CFUNCT},	/* ^^ */
				    {rescan, F_CFUNCT},	/* ^_ */
				    {forwline, F_CFUNCT},	/* SP */
};
static struct function diredc[] = {
				   {d_copy, F_CFUNCT},	/* c */
				   {d_del, F_CFUNCT},	/* d */
				   {d_findfile, F_CFUNCT},	/* e */
				   {d_findfile, F_CFUNCT},	/* f */
};
static struct function diredn[] = {
				   {forwline, F_CFUNCT},	/* n */
				   {d_ffotherwindow, F_CFUNCT},	/* o */
				   {backline, F_CFUNCT},	/* p */
				   {rescan, F_CFUNCT},	/* q */
				   {d_rename, F_CFUNCT},	/* r */
				   {rescan, F_CFUNCT},	/* s */
				   {rescan, F_CFUNCT},	/* t */
				   {d_undel, F_CFUNCT},	/* u */
				   {rescan, F_CFUNCT},	/* v */
				   {rescan, F_CFUNCT},	/* w */
				   {d_expunge, F_CFUNCT},	/* x */
};
static struct function direddl[] = {
				    {d_undelbak, F_CFUNCT},	/* del */
};

#ifndef	DIRED_XMAPS
#define	NDIRED_XMAPS	0	/* number of extra map sections */
#endif

static struct KEYMAPE (6 + NDIRED_XMAPS + IMAPEXT) diredmap = {
	                6 + NDIRED_XMAPS,
	                6 + NDIRED_XMAPS + IMAPEXT,
	               &rescan_default,
	{
#ifndef NO_HELP
		{
			                CCHR('@'), CCHR('H'), dirednul
		}              ,
#else
		{
			                CCHR('@'), CCHR('G'), dirednul
		}              ,
#endif
		{
			                CCHR('L'), CCHR('X'), diredcl
		}              ,
		{
			                CCHR('Z'), ' ', diredcz
		}              ,
		{
			                'c', 'f', diredc
		}              ,
		{
			                'n', 'x', diredn
		}              ,
		{
			                CCHR('?'), CCHR('?'), direddl
		}              ,
#ifdef	DIRED_XMAPS
		                DIRED_XMAPS,	/* map sections for dired
						 * mode keys	 */
#endif
	}
};
#endif

/*
 * give names to the maps, for use by help etc. If the map is to be bindable,
 * it must also be listed in the function name table below with the same
 * name. Maps created dynamicly currently don't get added here, thus are
 * unnamed. Modes are just named keymaps with functions to add/subtract them
 * from a buffer's list of modes.  If you change a mode name, change it in
 * modes.c also. 
 */

struct maps     map_table[] = {
/* fundamental map MUST be first entry */
			       {(struct keymap *) & fundmap, "fundamental"},
			       {(struct keymap *) & fillmap, "fill"},
			       {(struct keymap *) & indntmap, "indent"},
			       {(struct keymap *) & blinkmap, "blink"},
#ifdef	NOTAB
			       {(struct keymap *) & notabmap, "notab"},
#endif
			       {(struct keymap *) & overwmap, "overwrite"},
			       {(struct keymap *) & metamap, "esc prefix"},
			       {(struct keymap *) & cXmap, "c-x prefix"},
			       {(struct keymap *) & cX4map, "c-x 4 prefix"},
#ifndef NO_HELP
			       {(struct keymap *) & helpmap, "help"},
#endif
#ifndef NO_DIRED
			       {(struct keymap *) & diredmap, "dired"},
#endif
};

#define NMAPS	(sizeof map_table/sizeof(struct maps))
int             nmaps = NMAPS;	/* for use by rebind in extend.c */

char           *
map_name(map)
	struct keymap  *map;
{
	struct maps    *mp = &map_table[0];

	do {
		if (mp->p_map == map)
			return mp->p_name;
	} while (++mp < &map_table[NMAPS]);
	return (char *) NULL;
}

struct maps    *
name_mode(name)
	char           *name;
{
	struct maps    *mp = &map_table[0];

	if (!name)
		return NULL;
	do {
		if (strcmp(mp->p_name, name) == 0)
			return mp;
	} while (++mp < &map_table[NMAPS]);
	return NULL;
}

struct keymap  *
name_map(name)
	char           *name;
{
	struct maps    *mp;
	return (mp = name_mode(name)) == NULL ? (struct keymap *) NULL : mp->p_map;
}

/*
 * Warning: functnames MUST be in alphabetical order!  (due to binary search
 * in name_function.)  If the function is prefix, it must be listed with the
 * same name in the map_table struct above. 
 */

struct functnames functnames[] = {
#ifdef	AMIGA
#ifdef	DO_ICONIFY
				  {tticon, "amiga-iconify"},
#endif
#ifdef	DO_MENU
				  {amigamenu, "amiga-menu"},
#endif
#ifdef	CHANGE_COLOR
				  {modebackground, "amiga-mode-background"},
				  {modeforeground, "amiga-mode-foreground"},
				  {ttmode, "amiga-mode-rendition"},
#endif
#ifdef	CHANGE_FONT
				  {setfont, "amiga-set-font"},
#endif
#ifdef	CHANGE_COLOR
				  {textbackground, "amiga-text-background"},
				  {textforeground, "amiga-text-foreground"},
				  {tttext, "amiga-text-rendition"},
#endif
				  {togglewindow, "amiga-toggle-border"},
#ifdef	REXX
				  {rexxtopwindow, "amiga-window-to-top"},
#endif
				  {togglezooms, "amiga-zoom-mode"},
#endif				/* AMIGA */
#ifndef	NO_HELP
				  {apropos_command, "apropos"},
#endif
				  {fillmode, "auto-fill-mode"},
				  {indentmode, "auto-indent-mode"},
				  {backchar, "backward-char"},
				  {delbword, "backward-kill-word"},
				  {gotobop, "backward-paragraph"},
				  {backword, "backward-word"},
				  {gotobob, "beginning-of-buffer"},
				  {gotobol, "beginning-of-line"},
				  {blinkparen, "blink-matching-paren"},
				  {showmatch, "blink-matching-paren-hack"},
#ifdef	BSMAP
				  {bsmap, "bsmap-mode"},
#endif
				  {NULL, "c-x 4 prefix"},
				  {NULL, "c-x prefix"},
#ifndef NO_MACRO
				  {executemacro, "call-last-kbd-macro"},
#endif
				  {capword, "capitalize-word"},
#ifndef NO_DIR
				  {changedir, "cd"},
#endif
				  {copyregion, "copy-region-as-kill"},
#ifdef	REGEXP
				  {cntmatchlines, "count-matches"},
				  {cntnonmatchlines, "count-non-matches"},
#endif
				  {define_key, "define-key"},
				  {backdel, "delete-backward-char"},
				  {deblank, "delete-blank-lines"},
				  {forwdel, "delete-char"},
				  {delwhite, "delete-horizontal-space"},
#ifdef	REGEXP
				  {delmatchlines, "delete-matching-lines"},
			    {delnonmatchlines, "delete-non-matching-lines"},
#endif
				  {onlywind, "delete-other-windows"},
				  {delwind, "delete-window"},
#ifndef NO_HELP
				  {wallchart, "describe-bindings"},
				  {desckey, "describe-key-briefly"},
#endif
				  {digit_argument, "digit-argument"},
#ifndef NO_DIRED
				  {dired, "dired"},
				  {d_undelbak, "dired-backup-unflag"},
				  {d_copy, "dired-copy-file"},
				  {d_expunge, "dired-do-deletions"},
				  {d_findfile, "dired-find-file"},
			  {d_ffotherwindow, "dired-find-file-other-window"},
				  {d_del, "dired-flag-file-deleted"},
				  {d_otherwindow, "dired-other-window"},
				  {d_rename, "dired-rename-file"},
				  {d_undel, "dired-unflag"},
#endif
				  {lowerregion, "downcase-region"},
				  {lowerword, "downcase-word"},
				  {showversion, "emacs-version"},
#ifndef NO_MACRO
				  {finishmacro, "end-kbd-macro"},
#endif
				  {gotoeob, "end-of-buffer"},
				  {gotoeol, "end-of-line"},
				  {enlargewind, "enlarge-window"},
				  {NULL, "esc prefix"},
#ifdef DO_EVAL
				  {evalbuffer, "eval-current-buffer"},
				  {evalexpr, "eval-expression"},
#endif
				  {swapmark, "exchange-point-and-mark"},
				  {extend, "execute-extended-command"},
				  {fillpara, "fill-paragraph"},
				  {filevisit, "find-file"},
				  {poptofile, "find-file-other-window"},
				  {forwchar, "forward-char"},
				  {gotoeop, "forward-paragraph"},
				  {forwword, "forward-word"},
#ifndef	NO_MACRO
				  {macroset, "fset"},
#endif
				  {bindtokey, "global-set-key"},
				  {unbindtokey, "global-unset-key"},
				  {gotoline, "goto-line"},
#ifndef NO_HELP
				  {NULL, "help"},
				  {help_help, "help-help"},
#endif
				  {bufferinsert, "insert-buffer"},
				  {fileinsert, "insert-file"},
#ifndef	NO_MACRO
				  {insertmacro, "insert-kbd-macro"},
#endif
				  {fillword, "insert-with-wrap"},
				  {backisearch, "isearch-backward"},
				  {forwisearch, "isearch-forward"},
				  {justone, "just-one-space"},
#ifndef	NO_MACRO
				  {macroquery, "kbd-macro-query"},
#endif
				  {ctrlg, "keyboard-quit"},
				  {killbuffer, "kill-buffer"},
				  {killline, "kill-line"},
				  {killpara, "kill-paragraph"},
				  {killregion, "kill-region"},
				  {delfword, "kill-word"},
				  {listbuffers, "list-buffers"},
#ifdef DO_EVAL
				  {evalfile, "load"},
#endif
				  {localbind, "local-set-key"},
				  {localunbind, "local-unset-key"},
#ifndef NO_BACKUP
				  {makebkfile, "make-backup-files"},
#endif
#ifndef	NO_METAKEY
				  {do_meta, "meta-key-mode"},	/* better name, anyone? */
#endif
#ifdef	AMIGA
#ifdef	MOUSE
				  {mgotobob, "mouse-beginning-of-buffer"},
				  {mforwdel, "mouse-delete-char"},
			       {mdelwhite, "mouse-delete-horizontal-space"},
				  {mdelwind, "mouse-delete-window"},
				  {mgotoeob, "mouse-end-of-buffer"},
				  {menlargewind, "mouse-enlarge-window"},
				  {mkillline, "mouse-kill-line"},
				  {mkillregion, "mouse-kill-region"},
				  {mdelfword, "mouse-kill-word"},
				  {mreposition, "mouse-recenter"},
				  {mbackpage, "mouse-scroll-down"},
				  {mforwpage, "mouse-scroll-up"},
				  {amigamouse, "mouse-set-point"},
				  {mshrinkwind, "mouse-shrink-window"},
			      {msplitwind, "mouse-split-window-vertically"},
				  {myank, "mouse-yank"},
#endif
#endif
#ifndef	NO_MACRO
				  {namemacro, "name-last-kbd-macro"},
#endif
				  {negative_argument, "negative-argument"},
				  {newline, "newline"},
				  {indent, "newline-and-indent"},
				  {forwline, "next-line"},
#ifdef	NOTAB
				  {notabmode, "no-tab-mode"},
#endif
				  {notmodified, "not-modified"},
				  {openline, "open-line"},
				  {nextwind, "other-window"},
				  {overwrite, "overwrite-mode"},
#ifdef	PREFIXREGION
				  {prefixregion, "prefix-region"},
#endif
				  {backline, "previous-line"},
#ifdef	GOSMACS
				  {prevwind, "previous-window"},
#endif
#ifdef	VMS
				  {spawncli, "push-to-dcl"},
#endif
#ifndef NO_DIR
				  {showcwdir, "pwd"},
#endif
				  {queryrepl, "query-replace"},
#ifdef	REGEXP
				  {re_queryrepl, "query-replace-regexp"},
#endif
				  {quote, "quoted-insert"},
#ifdef	REGEXP
				  {re_searchagain, "re-search-again"},
				  {re_backsearch, "re-search-backward"},
				  {re_forwsearch, "re-search-forward"},
#endif
				  {reposition, "recenter"},
				  {refresh, "redraw-display"},
				  {revertbuffer, "revert-buffer"},
#ifdef	REXX
				  {rexxcommand, "rexx"},
				  {rexxbuffer, "rexx-buffer"},
				  {rexxbuflist, "rexx-buffer-list"},
				  {rexxdisplay, "rexx-display"},
				  {rexxexitcommand, "rexx-do-on-exit"},
				  {rexxcomregion, "rexx-do-region"},
				  {rexxinsert, "rexx-insert"},
				  {rexxline, "rexx-line"},
				  {rexxlock, "rexx-lock"},
				  {rexxmark, "rexx-mark"},
				  {rexxpoint, "rexx-point"},
				  {rexxregion, "rexx-region"},
				  {rexxrequest, "rexx-request"},
				  {rexxreqbuf, "rexx-request-buffer"},
				  {rexxreqfunc, "rexx-request-function"},
				  {rexxreqmacro, "rexx-request-macro"},
				  {rexxunlock, "rexx-unlock"},
				  {rexxwait, "rexx-wait"},
				  {rexxwindow, "rexx-window"},
#endif
				  {filesave, "save-buffer"},
				  {quit, "save-buffers-kill-emacs"},
				  {savebuffers, "save-some-buffers"},
				  {backpage, "scroll-down"},
#ifdef	GOSMACS
				  {back1page, "scroll-one-line-down"},
				  {forw1page, "scroll-one-line-up"},
#endif
				  {pagenext, "scroll-other-window"},
				  {forwpage, "scroll-up"},
				  {searchagain, "search-again"},
				  {backsearch, "search-backward"},
				  {forwsearch, "search-forward"},
				  {selfinsert, "self-insert-command"},
#ifdef	REGEXP
				  {setcasefold, "set-case-fold-search"},
#endif
				  {set_default_mode, "set-default-mode"},
				  {setfillcol, "set-fill-column"},
				  {setmark, "set-mark-command"},
#ifdef	PREFIXREGION
				  {setprefix, "set-prefix-string"},
#endif
				  {shrinkwind, "shrink-window"},
#ifdef	NOTAB
				  {space_to_tabstop, "space-to-tabstop"},
#endif
				  {splitwind, "split-window-vertically"},
#ifndef NO_MACRO
				  {definemacro, "start-kbd-macro"},
#endif
#ifdef	VMS
				  {attachtoparent, "suspend-emacs"},
#else
				  {spawncli, "suspend-emacs"},
#endif
				  {usebuffer, "switch-to-buffer"},
			     {poptobuffer, "switch-to-buffer-other-window"},
				  {twiddle, "transpose-chars"},
				  {universal_argument, "universal-argument"},
				  {upperregion, "upcase-region"},
				  {upperword, "upcase-word"},
				  {showcpos, "what-cursor-position"},
				  {filewrite, "write-file"},
				  {yank, "yank"},
};

#define NFUNCT	(sizeof(functnames)/sizeof(struct functnames))

int             nfunct = NFUNCT;/* used by help.c */

#ifdef	LATTICE_50
static char     a;		/* Sigh */
#endif

/*
 * The general-purpose version of ROUND2 blows osk C (2.0) out of the water.
 * (reboot required)  If you need to build a version of mg with less than 32
 * or more than 511 functions, something better must be done. The version
 * that should work, but doesn't is: #define ROUND2(x)
 * (1+((x>>1)|(x>>2)|(x>>3)|(x>>4)|(x>>5)|(x>>6)|(x>>7)|\
 * (x>>8)|(x>>9)|(x>>10)|(x>>11)|(x>>12)|(x>>13)|(x>>14)|(x>>15))) 
 */
#define ROUND2(x) (x<128?(x<64?32:64):(x<256?128:256))

static
name_fent(fname, flag)
	register char  *fname;
	int             flag;
{
	register int    try;
	register int    x = ROUND2(NFUNCT);
	register int    base = 0;
	register int    notit;

	do {
		/* + can be used instead of | here if more efficent.	 */
		if ((try = base | x) < NFUNCT) {
			if ((notit = strcmp(fname, functnames[try].n_name)) >= 0) {
				if (!notit)
					return try;
				base = try;
			}
		}
	} while ((x >>= 1) || (try == 1 && base == 0));	/* try 0 once if needed */
	return flag ? base : -1;
}

/*
 * Translate from function name to function pointer, using binary search. 
 */

int
                (*
		 name_function(fname)) ()
	char           *fname;
{
	int             i;
	if ((i = name_fent(fname, FALSE)) >= 0 && functnames[i].n_funct)
		return functnames[i].n_funct;
	return NULL;
}

/* complete function name */

complete_function(fname, c)
	register char  *fname;
{
	register int    i, j, k, l;
	int             oj;

	i = name_fent(fname, TRUE);
	for (j = 0; (l = fname[j]) && functnames[i].n_name[j] == l; j++) {
	}
	if (fname[j] != '\0') {
		if (++i >= NFUNCT)
			return -1;	/* no match */
		for (j = 0; (l = fname[j]) && functnames[i].n_name[j] == l; j++) {
		}
		if (fname[j] != '\0')
			return -1;	/* no match */
	}
	if (c == CCHR('M') && functnames[i].n_name[j] == '\0')
		return -3;
	for (k = i + 1; k < NFUNCT; k++) {	/* find last match */
		for (l = 0; functnames[k].n_name[l] == fname[l]; l++) {
		}
		if (l < j)
			break;
	}
	k--;
	oj = j;
	if (k > i) {		/* multiple matches */
		while ((l = functnames[i].n_name[j]) == functnames[k].n_name[j]) {
			fname[j++] = l;
			if (l == '-' && c == ' ')
				break;
		}
		if (j == oj)
			return -2;	/* ambiguous	 */
	} else {		/* single match */
		while (l = functnames[i].n_name[j]) {
			fname[j++] = l;
			if (!ISWORD(l) && c == ' ')
				break;
		}
		if (c == CCHR('M')) {
			fname[j] = '\0';
			return -3;
		}
	}
	fname[j] = '\0';
	return j - oj;
}

/* translate from function pointer to function name. */

char           *
function_name(fpoint)
	register int    (*fpoint) ();
{
	register struct functnames *fnp = &functnames[0];

	if (fpoint == (int (*) ()) NULL)
		return (char *) NULL;	/* ambiguous */
	do {
		if (fnp->n_funct == fpoint)
			return fnp->n_name;
	} while (++fnp < &functnames[NFUNCT]);
	return (char *) NULL;
}
