/*======================================================================*\
|*		Editor mined						*|
|*		Function key dispatcher					*|
\*======================================================================*/

#include "mined.h"
#include "io.h"


/*======================================================================*\
|*	Debug function dispatching					*|
\*======================================================================*/

#define dont_debug_dispatch

#ifdef debug_dispatch
#define trace_dispatch(func)	do_debug_dispatch (func)
#else
#define trace_dispatch(func)	
#endif

#ifdef debug_dispatch
static
void
do_debug_dispatch (func)
  char * func;
{
  if (keyshift & applkeypad_mask) {
	printf ("appl-keypad ");
  }
  if (keyshift & ctrl_mask) {
	printf ("ctrl-");
  }
  if (keyshift & alt_mask) {
	printf ("alt-");
  }
  if (keyshift & shift_mask) {
	printf ("shift-");
  }
  printf ("%s\n", func);
}
#endif


/*======================================================================*\
|*	Dispatch function keys and some keypad keys to mined functions	*|
\*======================================================================*/

/**
   HOMEkey () is invoked by a Home key on the right (application) keypad;
   function configurable
 */
void
HOMEkey ()
{
  trace_dispatch ("Home");

#ifdef weird_stuff_disabling_alt_in_xterm
  if ((keyshift & (alt_mask | applkeypad_mask)) == alt_mask) {
	smallHOMEkey ();
	return;
  }
#endif

  if (keyshift & shift_mask) {
	keyshift = 0;
	MARK ();
  } else if (keyshift & ctrl_mask) {
	keyshift = 0;
	BLINE ();
  } else {
	if (mined_keypad == ! (keyshift & alt_mask)) {
		MARK ();
	} else {
		BLINE ();
	}
  }
}

/**
   smallHOMEkey () is invoked by a Home key on the small keypad;
   function configurable
 */
void
smallHOMEkey ()
{
  trace_dispatch ("smallHome");

  if (keyshift & shift_mask) {
	keyshift = 0;
	MARK ();
  } else if (keyshift & ctrl_mask) {
	keyshift = 0;
	GO_LINEBEGIN ();
  } else {
	if (mined_keypad == ! (keyshift & alt_mask)) {
		BLINE ();
	} else {
		MARK ();
	}
  }
}

/**
   ENDkey () is invoked by an End key on the right (application) keypad;
   function configurable
 */
void
ENDkey ()
{
  trace_dispatch ("End");

#ifdef weird_stuff_disabling_alt_in_xterm
  if ((keyshift & (alt_mask | applkeypad_mask)) == alt_mask) {
	smallENDkey ();
	return;
  }
#endif

  if (keyshift & shift_mask) {
	keyshift = 0;
	COPY ();
  } else if (keyshift & ctrl_mask) {
	keyshift = 0;
	ELINE ();
  } else {
	if (mined_keypad == ! (keyshift & alt_mask)) {
		COPY ();
	} else {
		ELINE ();
	}
  }
}

/**
   smallENDkey () is invoked by an End key on the small keypad;
   function configurable
 */
void
smallENDkey ()
{
  trace_dispatch ("smallEnd");

  if (keyshift & shift_mask) {
	keyshift = 0;
	COPY ();
  } else if (keyshift & ctrl_mask) {
	keyshift = 0;
	GO_LINEEND ();
  } else {
	if (mined_keypad == ! (keyshift & alt_mask)) {
		ELINE ();
	} else {
		COPY ();
	}
  }
}


#define not_alt_del_always_deletes_char
#define alt_alt_may_delete_char

#ifdef alt_del_always_deletes_char
#define cut_cond (mined_keypad && ! (keyshift & (alt_mask | applkeypad_mask)))
#else
#ifdef alt_alt_may_delete_char
#define cut_cond (mined_keypad == ! (keyshift & alt_mask))
#else
#define cut_cond (mined_keypad == ! ((keyshift & (alt_mask | applkeypad_mask)) == (alt_mask | applkeypad_mask)))
#endif
#endif

/**
   DELkey () is invoked by a Delete function key, 
   often KP_Delete on right keypad;
   function configurable
 */
void
DELkey ()
{
  trace_dispatch ("Delete");

  if ((keyshift & ctrl_mask) && ! (keyshift & alt_mask)) {
	/*keyshift = 0;*/
	DCC ();
  } else if ((keyshift & shift_mask) && ! (keyshift & alt_mask)) {
	keyshift = 0;
	CUT ();
  } else {
	/*
	mined_keypad alt_mask applkeypad_mask	alt-KP	alt-DEL	alt-ALT
		1	0	0		cut !	cut	cut
		1	0	1		*	*	*
		1	1	0		cut	del	del
		1	1	1		del	del	del
		0	0	0		del !	del	del
		0	0	1		*	*	*
		0	1	0		del	del	cut
		0	1	1		cut	del	cut
	*/
	if (cut_cond) {
		CUT ();
	} else {
		DCC ();
	}
  }
}

/**
   smallDELkey () is invoked by the small keypad ("extended") Delete key
 */
void
smallDELkey ()
{
  trace_dispatch ("smallDelete");

  keyshift |= ctrl_mask;
  DELkey ();
}

/**
   DELchar () is invoked by a DEL character unless reconfigured to 
   map to DPC;
   the key may be a Delete function key (on small keypad, if so configured),
   or the Backarrow key (unless configured to emit the BackSpace character)
 */
void
DELchar ()
{
  trace_dispatch ("DEL");

  if (keyshift & shift_mask) {
	keyshift = 0;
	CUT ();
  } else if (keyshift & ctrl_mask) {
	DCC ();
  } else {
	if (hop_flag > 0 || keyshift & alt_mask) {
		hop_flag = 0;
		CUT ();
	} else {
		DCC ();
	}
  }
}

void
INSkey ()
{
  trace_dispatch ("Insert");

  if (keyshift & alt_mask) {
	keyshift = 0;
	YANKRING ();
  } else if (keyshift & ctrl_mask) {
	keyshift = 0;
	PASTEstay ();
  } else {
	PASTE ();
  }
}

/**
   smallINSkey () is invoked by the small keypad ("extended") Insert key
 */
void
smallINSkey ()
{
  trace_dispatch ("smallInsert");

  keyshift |= ctrl_mask;
  INSkey ();
}


/**
   Display function key help lines
 */
static voidfunc fhelp_func = F1;
static char fhelp_keyshift = 0;

void
display_FHELP ()
{
/* use the following screen attributes:
			unicode indicator (cyan background)
			highlight (red background)
			reverse
			plain (normal)
*/
  if (fhelp_func == COMPOSE) {
	status_uni ("ctrl- , ¸/ͺ . ˙/῾ :/\" ¨ ; ˛ ' ´tonos ´ oxia - ¯ <  ̌/᾿ ( ˘ )  ̑ & hook ^ ~ ` / °");
  } else if (fhelp_func == key_1) {
    if (fhelp_keyshift == altctrl_mask) {
	status_uni ("alt-ctrl- 1 ˘/ ̛ + ´ 2 ˘/ ̛ + ` 3 ˘/ ̛ +  ̉ 4 ˘/ ̛ + ~ 5 ˘/ ̛ +  ̣ 6 ῞ 7 ῝ 8 ῟ 9  0 ");
    } else if (fhelp_keyshift == ctrl_mask) {
	status_uni ("ctrl- 1 ´ 2 ` 3  ̉ 4 ~ 5  ̣ 6 ^ 7 ˘ 8  ̛ 9 / 0 °");
    } else {
	status_uni ("alt- 1 ^ + ´ 2 ^ + ` 3 ^ +  ̉ 4 ^ + ~ 5 ^ +  ̣ 6 ῎ 7 ῍ 8 ῏ 9  0 ");
    }
  } else {
    if ((fhelp_keyshift & altctrlshift_mask) == altshift_mask) {
	status_uni ("alt-shift-               F4 Kill window! F5 ˘ F6 ˙");
    } else if ((fhelp_keyshift & altctrlshift_mask) == ctrlshift_mask) {
	status_uni ("ctrl-shift-                         F5 ˛ F6 ¯    F8 LineRepl F9 FindChar");
    } else if (fhelp_keyshift & alt_mask) {
	status_uni ("alt-   F2 SaveAs    F4 Kill window!       F8 SearchBack F9 NextBack F10 FlagMenu");
    } else if (fhelp_keyshift & ctrl_mask) {
	status_uni ("ctrl- F2 SaveTo  F4 PastePrev F5 °/¸ F6 ^  F8 Subst/Confirm  F10 InfoMenu");
    } else if (fhelp_keyshift & shift_mask) {
	status_uni ("shift- F2 Save! F3 CaseTog F4 WrtBuf F5 ~ F6 `  F8 Subst F9 FindIdf F10 Menu");
    } else {
	status_uni ("       F2 Save F3 Edit F4 InsFile F5 \" F6 ´  F8 Search F9 Next F10 Filemenu");
    }
  }
}

void
toggle_FHELP ()
{
  always_disp_help = ! always_disp_help;
}

void
FHELP (func)
  voidfunc func;
{
  fhelp_func = func;
  fhelp_keyshift = keyshift;
  if (hop_flag > 0) {
	hop_flag = 0;
	always_disp_help = ! always_disp_help;
  } else {
	display_FHELP ();
  }
}


void
F1 ()
{
  trace_dispatch ("F1");

  if (keyshift & altctrlshift_mask) {
	FHELP (F1);
  } else {
	HELP ();
  }
}

void
F2 ()
{
  trace_dispatch ("F2");

  if (keyshift & ctrl_mask) {
	/* enforce creation of marker position memory file @mined.mar */
	hop_flag = 1;
  }

  if (keyshift & alt_mask) {
	keyshift = 0;
	SAVEAS ();
  } else if (keyshift & shift_mask) {
	keyshift = 0;
	WTU ();
  } else if (keyshift & ctrl_mask) {
	keyshift = 0;
	EXED ();
  } else {
	WT ();
  }
}

void
F3 ()
{
  trace_dispatch ("F3");

  if (keyshift & ctrl_mask) {
	keyshift = 0;
	VIEW ();
  } else if (keyshift & shift_mask) {
	keyshift = 0;
	LOWCAPWORD ();
  } else {
	EDIT ();
  }
}

void
F4 ()
{
  trace_dispatch ("F4");

  if (keyshift & shift_mask) {
	keyshift = 0;
	WB ();
  } else if (keyshift & ctrl_mask) {
	keyshift = 0;
	YANKRING ();
  } else {
	INSFILE ();
  }
}

#ifdef dispatch_accents
/* accent prefix keys are now handled generically in edit.c:
  insert_prefix (F5);
  insert_prefix (F6);
 */
void
F5 ()
{
  trace_dispatch ("F5");

  /*	standard function key assignment:
		F5	F6
		"	´
	shift	~	`
	ctrl	°	^
  */
  if (keyshift & ctrl_mask) {
	keyshift = 0;
	insert_angstrom ();
  } else if (keyshift & shift_mask) {
	keyshift = 0;
	insert_tilde ();
  } else {
	insert_diaeresis ();
  }
}

void
F6 ()
{
  trace_dispatch ("F6");

  /*	standard function key assignment:
		F5	F6
		"	´
	shift	~	`
	ctrl	°	^
  */
  if (keyshift & ctrl_mask) {
	keyshift = 0;
	insert_circumflex ();
  } else if (keyshift & shift_mask) {
	keyshift = 0;
	insert_grave ();
  } else {
	insert_acute ();
  }
}
#endif

void
FIND ()
{
  if ((keyshift & ctrlshift_mask) == ctrlshift_mask) {
	keyshift = 0;
	if (hop_flag > 0) {
		Stag ();
	} else {
		LR ();
	}
  } else if ((keyshift & altctrl_mask) == altctrl_mask) {
	keyshift = 0;
	if (hop_flag > 0) {
		hop_flag = 0;
		SCURCHAR (REVERSE);
	} else {
		REPL ();
	}
  } else if (keyshift & ctrl_mask) {
	keyshift = 0;
	if (hop_flag > 0) {
		hop_flag = 0;
		SCURCHAR (FORWARD);
	} else {
		REPL ();
	}
  } else if (keyshift & shift_mask) {
	keyshift = 0;
	if (hop_flag > 0) {
		hop_flag = 0;
		Stag ();
	} else {
		GR ();
	}
  } else if (keyshift & alt_mask) {
	keyshift = 0;
	SRV ();
  } else {
	SFW ();
  }
}

void
AGAIN ()
{
  if ((keyshift & altctrlshift_mask) == altctrlshift_mask) {
	keyshift = 0;
	SCURCHAR (REVERSE);
  } else if ((keyshift & ctrlshift_mask) == ctrlshift_mask) {
	keyshift = 0;
	SCURCHAR (FORWARD);
  } else if ((keyshift & altshift_mask) == altshift_mask) {
	keyshift = 0;
	SIDF (REVERSE);
  } else if (keyshift & shift_mask) {
	keyshift = 0;
	SIDFW ();
  } else if (keyshift & alt_mask) {
	RSreverse ();
  } else {
	RS ();
  }
}

void
F7 ()
{
  trace_dispatch ("F7");

  FIND ();
}

void
F8 ()
{
  trace_dispatch ("F8");

  FIND ();
}

void
F9 ()
{
  trace_dispatch ("F9");

  AGAIN ();
}

void
F10 ()
{
  trace_dispatch ("F10");

  if (keyshift & alt_mask) {
	keyshift = 0;
	handleFlagmenus ();
  } else if (keyshift & shift_mask) {
	keyshift = 0;
	QUICKMENU ();
  } else if (keyshift & ctrl_mask) {
	keyshift = 0;
	handleFlagmenus ();
  } else {
	FILEMENU ();
  }
}

void
F11 ()
{
  trace_dispatch ("F11");

  if (keyshift & alt_mask) {
	if (keyshift & shift_mask) {
		hop_flag = 1;
	}
	search_wrong_enc ();
  } else if ((keyshift & ctrlshift_mask) == ctrlshift_mask) {
	hop_flag = 1;
	changeuni ();
  } else if (keyshift & shift_mask) {
	keyshift = 0;
	hop_flag = 1;
	LOWCAP ();
  } else if (keyshift & ctrl_mask) {
	UML (' ');
  } else {
	LOWCAP ();
  }
}

void
F12 ()
{
  trace_dispatch ("F12");

  if (keyshift & alt_mask) {
	toggleKEYMAP ();
  } else if (keyshift & ctrl_mask) {
	setupKEYMAP ();
  } else {
	SAVPOS ();
  }
}


/*======================================================================*\
|*				End					*|
\*======================================================================*/
