#include windows.sh
#include dialog.sh

#define KEYMAC_ED_ADD_CTRL  1000
#define KEYMAC_ED_DEL_CTRL  1001
#define KEYMAC_ED_CHNG_CTRL 1002
#define KEYMAC_ED_LIST_CTRL 1200

prototype PKEYMAC {
  int KEYMAC_K_PROMPT (str title, int k1, k2);
}

MACRO_FILE KEYMAC;
/*******************************************************************************
																MULTI-EDIT MACRO

Name:	KEYMAC

Description: Macros that handle keystroke macros.

KEYMAC_LIST		- Brings up a list of keystroke macros.
KEYMAC_EDIT		- Allows user to edit individual keystrokes in a keystroke macro.
KEYMAC_CHECK	- Checks for key assignment conflicts in keystroke macros.
DOUBLE_127		- Finds any ASCII 127 '' characters in a keystroke macro data
								string and doubles it so it may be stored in .DB format.
KEYMAC_K_PROMPT - Provides a prompt for a keystroke for keystroke macro editing.
KEYMAC_ADD_TEMP - Allows user to save a temporary keystroke macros permanently.
MAKEKEYMAC		- Takes the keystroke macro information and puts it into
								a global variable.

							 (C) Copyright 1991 by American Cybernetics, Inc.
*******************************************************************************/

macro KEYMAC_LIST trans2 {
/*******************************************************************************
																MULTI-EDIT MACRO

Name:	KEYMAC_LIST

Description: Brings up a list of keystroke macros.

							 (C) Copyright 1991 by American Cybernetics, Inc.
*******************************************************************************/
	str K_Str[2048];
	int T_Mode,K1,K2;

/* Unload all keys first */
	RM('KEYMAC_LOAD /LM=2/KW=1');

/* Bring up editing menu */
Edit_Menu:
	K_Str = '';
	if (global_int('!KMTRANS_COUNT') > 0) {
		Set_Global_Str('@KMB1', '/TP=11/T=Save temporary keystroke macro/KC=<F10>/W=34/K1=0/K2=68/R=100/C=6');
		K_Str = '/EBN=@KMB/EBC=1';
	}
  RM('DB /ABT=Playback/CBT=Done/NDF=1/F=MECONFIG/DPT=KEYMAC.DB/HF=MEWHDRS.DB/HPT=KEYMAC.HDR/NOALPHA=1/PRE=KM/GLO=@KMG#/LO=3/H=Keystroke Macros/S=' +
		Parse_Str('/S=',MParm_Str) +  K_Str +
    '/CANMAC=1/LT=Recorded Macro Manager/DT=Editing Recorded Macro' +
    '/MACRO=KEYMAC_CHECK');
	Set_Global_Str('@KMB1', '');

	T_Mode = Return_Int;
	if (T_Mode == 100) {
		RM('KEYMAC_ADD_TEMP');
		Goto EDIT_MENU;
	}
/* Load new list */
	RM('KEYMAC_LOAD');
	if (T_Mode == 1) {
/* Run keystroke macro from menu by temporarily assigning it to a non existant
keystroke, invoking the keystroke, then unassigning it. */
		K_Str = Global_Str('@KMG#');
		T_Mode = Parse_int('M=',K_Str);
		if (T_Mode == mode) {
/* Don't do it unless we are in the same mode */
			set_global_str('@KMTEMP!#',Reconvert_String(Parse_str('S=',K_Str)));
			global_to_key($FFFF,'@KMTEMP!#',T_Mode);
			Pass_Key($FF,$FF);
		}
	}

}

void KEYMAC_EDIT_DEL() {

  int hlist = GetDlgItem(parse_int("/DLGHANDLE=",mparm_str),Keymac_Ed_list_Ctrl);

  sendmessage(hlist, LB_DELETESTRING, c_line - 1, 0);
  del_line;
  sendmessage(hlist, LB_SETCURSEL, c_line - 1, 0);
  RETURN();
}

int KM_CHK_SHIFTSTAT(int check_mode) {
  int ret_value = 0,
      search_result;
  str t_str;

  if (check_mode & 2) {
    t_str = "Shift";
    Call DO_CHECK;
    if (search_result) {
      ret_value |= 2;
    }
  }


  if (check_mode & 4) {
    t_str = "Ctrl";
    Call DO_CHECK;
    if (search_result) {
      ret_value |= 4;
    }
  }


  if (check_mode & 8) {
    t_str = "Alt";
    Call DO_CHECK;
    if (search_result) {
      ret_value |= 8;
    }
  }

  RETURN(ret_value);


str xx;
DO_CHECK:
  mark_pos;
  search_result = 0;

  if (parse_str("KNAME=",get_line) != t_str) { // don't do the check if the key is the same as what we are looking for
    if (Find_Text("KNAME=" + t_str + "$|[^+]", 0, _Backward | _RegExp)) {
      if (xpos("KeyDown",get_line,6)) {  // see if it is a keydown
        search_result = 1;
      }
    }
  }
  goto_Mark;
  RET;
}

int KEYMAC_EDIT_CHNG(int dlghandle = parse_int("/DLGHANDLE=",mparm_str)) {
  int hlist = GetDlgItem(dlghandle,Keymac_Ed_list_Ctrl),
      paraml,
      t_int,
      k1,
      msg1,
      msg2,
      increment,
      paramh = parse_int("PARAMH=",get_line) & 0x7FFF,
      t_time = parse_int("TIME=",get_line),
      ret_value = 0,
      t_insert_mode = insert_mode;

  str kname, msgtext;

  if (keymac_K_Prompt("Edit Keystroke", parse_int("K1=",Get_line), parse_int("K2=",Get_line))) {
    insert_mode = true;
    paraml = (return_int & 0xff);
    paraml = paraml | (MapVirtualKey(paraml,0) << 8);

    paramh = paramh | (return_int & 0x8000);

    t_int = KM_CHK_SHIFTSTAT(0xF);
    msgtext = "";
    msg1 = WM_KEYDOWN;
    msg2 = WM_KEYUP;

    if (return_int & 0x0200) { // shift
      if (!(t_int & 2)) {
// if not already in a shifted state, add the appropriate key messages
        kname = "Shift";
        paramh = 1;
        k1 = VK_SHIFT;
        increment = 1;
        call INSERT_SHIFTSTAT;
      }
    }
    if (return_int & 0x0400) { // ctrl
      if (!(t_int & 4)) {
        kname = "Ctrl";
        paramh = 1;
        k1 = VK_CONTROL;
        increment = 2;
        call INSERT_SHIFTSTAT;
      }
    }
    if (return_int & 0x0800) { // alt
      if (!(t_int & 8)) {
        msg1 = WM_SYSKEYDOWN;
        msg2 = WM_SYSKEYUP;
        msgtext = "SYS";
        kname = "Alt";
        paramh = 1;
        k1 = VK_MENU;
        increment = 3;
        call INSERT_SHIFTSTAT;
      }
    }

    put_line("MSGTXT=" + parse_str("MSGTXT=",get_line) +
            "KNAME=" + return_str +
            "MSG=" + parse_str("MSG=",get_line) +
            "PARAML=" + str(paramL) +
            "PARAMH=" + str(PARAMH) +
            "TIME=" + parse_str("TIME=",get_line) +
            "K1=" + str(return_int & 0xff) +
            "K2=" + str(return_int >> 8)
            );
//    sendmessage(hlist, LB_ADDSTRING, c_line - 1, 0);
    ret_value = 1;
  }

  insert_mode = t_insert_mode;

  sendmessage(hlist, LB_SETCURSEL, c_line - 1, 0);

  return_int = 0;
  RETURN(ret_value);

INSERT_SHIFTSTAT:
  goto_col(1);
  cr;
  up;
  put_Line("MSGTXT=" + msgtext + "KeyDownKNAME=" + kname +
          "MSG=" + str(msg1) +
          "PARAML=" + str((MapVirtualKey(k1,0) << 8) | k1) +
          "PARAMH=" + str(paramh) +
          "TIME=" + str(t_time - increment) +
          "K1=" + str(k1) +
          "K2=1"
          );
  sendmessage(hlist, LB_ADDSTRING, c_line - 1, 0);
  down;
  eol;
  cr;
  put_Line("MSGTXT=" + msgtext + "KeyUpKNAME=" + kname +
          "MSG=" + str(msg2) +
          "PARAML=" + str((MapVirtualKey(k1,0) << 8) | k1) +
          "PARAMH=" + str(paramh) +
          "TIME=" + str(t_time + increment) +
          "K1=" + str(k1) +
          "K2=" + str(0x02)
          );
  up;
  sendmessage(hlist, LB_ADDSTRING, c_line - 1, 0);
  RET;

}

void KEYMAC_EDIT_ADD() {
  int dlghandle = parse_int("/DLGHANDLE=",mparm_str),
      hlist = GetDlgItem(dlghandle,Keymac_Ed_list_Ctrl),
      t_insert_mode = insert_mode;

  str t_str[2048];

  insert_mode = true;
  goto_col(1);
  cr;
  up;
  put_line("MSGTXT=KeyDownMSG=" + str(WM_KEYDOWN));

  if (keymac_edit_chng(dlghandle)) {
    t_str = get_line;
    sendmessage(hlist, LB_ADDSTRING, c_line - 1, 0);
// put matching keyup event
    eol;
    cr;
    put_line("MSGTXT=KeyUp" +
            "KNAME=" + parse_str("KNAME=",t_str) +
            "MSG=" + str(WM_KEYUP) +
            "PARAML=" + parse_str("PARAML=",t_str) +
            "PARAMH=" + parse_str("PARAMH=",t_str) +
            "TIME=" + str(parse_int("TIME=",t_str) + 1) +
            "K1=" + parse_str("K1=",t_str) +
            "K2=" + parse_str("K2=",t_str)
            );
    sendmessage(hlist, LB_ADDSTRING, c_line - 1, 0);
  } else {
    del_line;
  }

  insert_mode = t_insert_mode;

return_int = 0;

  RETURN();

}

void KEYMAC_EDIT() trans2 {
/*******************************************************************************
																MULTI-EDIT MACRO

Name:	KEYMAC_EDIT

Description: Allows the user to edit inividual keystrokes in a keystroke macro

							 (C) Copyright 1991 by American Cybernetics, Inc.
*******************************************************************************/
  str Key_Buf[2048], t_key_buf[2048];
  Str tstr[256], tstr2[40], T_Return_Str;
  int Index, Active_Window, Menu_Window,
      param, k1, k2;
  int Col, Row, Result, Choice,
      check_mode = 0;
  int Old_Row, T_Insert_Mode, TBc, T_Refresh, T_Truncate_Spaces,
  dlg;
  struct TEventMsg rs;


//str xx[2048];

  Active_Window     = Window_Id;
	T_Truncate_Spaces = Truncate_Spaces;
  T_Return_Str      = Return_Str;
  T_Refresh         = Refresh;
  T_Insert_Mode     = Insert_Mode;
  Refresh           = False;

  Choice  = 1;
	Old_Row = 1;
	Row = Parse_Int('/Y=',MParm_Str);
	if (Row < 4) {
		Row = 4;
	}
	Col = Parse_Int('/X=',MParm_Str);
	if (Col < 1) {
		Col = 1;
	}
  Key_Buf = t_key_buf = Reconvert_String(Global_Str('@KM!'));

//xx = key_buf;

	Create_Window;
  Menu_Window   = Window_Id;
  File_Name     = Fexpand('KEYMAC.TMP');

  int l = svl(key_buf);
  while (l > 0) {
    str_to_struct (rs, key_buf);
    tstr = "MSGTXT=";
    switch ( rs.message )
    {
      // Handle Keyboard cases
      case WM_KEYDOWN :
        tstr += "KeyDown";
        goto keystr;
      case WM_SYSKEYDOWN :
        tstr += "SysKeyDown";
        goto keystr;
      case WM_KEYUP :
        tstr += "KeyUp";
        goto keystr;
      case WM_SYSKEYUP :
        tstr += "SysKeyUp";
KeyStr:
        param = ((rs.paramL & 0xff00) << 8) | ((rs.paramH & 0x8000) << 9) | (rs.paramH & 0x7fff);
//        k1 = MapVirtualKey((rs.paramL & 0xFF),2);
        k1 = (rs.paramL & 0xFF);

        GetKeyNameText (param, tstr2, 30);
        put_line("KNAME=" + tstr2); // we do this so that KM_CHK_SHIFTSTAT will work
// we need to check the shift status and artificially set the value k2
        k2 = 1 | KM_CHK_SHIFTSTAT(check_mode);
//        k2 = 1;

//GetKeyNameText (param, tstr2, 30);

        tstr2 = make_key_name(make_word(k1, k2));

        if (tstr2 == "Shift") {
          check_mode |= 2;
        }
        if (tstr2 == "Ctrl") {
          check_mode |= 4;
        }
        if (tstr2 == "Alt") {
          check_mode |= 8;
        }

        tstr = tstr +
              "KNAME=" + tstr2 +
              "MSG=" + str(rs.message) +
              "PARAML=" + str(rs.paramL) +
              "PARAMH=" + str(rs.paramH) +
              "TIME=" + str(rs.time) +
              "K1=" + str(k1) +
              "K2=" + str(k2);
        break;
      // Handle Mouse Cases

    }

    Put_Line(tstr);
    key_buf = Copy (Key_buf, 11, l - 10);
    l = svl (key_buf);
		Down;
	}
	File_Changed = False;
  Tof;

  DlgCreate( dlg );

  DlgAddCtrl( dlg,
              DLG_BitmapStatic,
              "BT_GN_122",
              1,
              1,
              0,
              0,
              1100,
              0,
              "" );

  DlgAddCtrl( dlg,
              Dlg_ListBox,
              "MSGTXT=/W=25KNAME=/W=30",
              15,
              1,
              50,
              6,
              KEYMAC_ED_LIST_CTRL,
              0,
              '/INCO=1/WIN='+str(cur_window));

  DlgAddCtrl( dlg,
              DLG_PushButton,
              "&Add",
              1,
              3,
              Dlg_StanBtnWidth,
              0,
              KEYMAC_ED_ADD_CTRL,
              0,
              "/R=10/M=KEYMAC_EDIT_ADD");

  DlgAddCtrl( dlg,
              DLG_PushButton,
              "&Delete",
              Dlg_PosOffset,
              DLG_PosOffset + Dlg_units + 18,
              Dlg_StanBtnWidth,
              0,
              KEYMAC_ED_DEL_CTRL,
              0,
              "/R=11/M=KEYMAC_EDIT_DEL");

  DlgAddCtrl( dlg,
              DLG_PushButton,
              "&Change",
              Dlg_PosOffset,
              DLG_PosOffset + dlg_units + 18,
              Dlg_StanBtnWidth,
              0,
              KEYMAC_ED_CHNG_CTRL,
              0,
              "/R=12/M=KEYMAC_EDIT_CHNG");

  DlgAddCtrl( dlg,
              DLG_PushButton,
              "OK",
              1,
              Dlg_PosOffset + dlg_units + 20,
              Dlg_StanBtnWidth,
              0,
              1003,
              Dlgf_DefButton,
              "/R=1");

  DlgAddCtrl( dlg,
              DLG_PushButton,
              "Cancel",
              DLG_PosOffset + Dlg_StanBtnWidth + 2,
              DLG_PosOffset,
              Dlg_StanBtnWidth,
              0,
              1004,
              0,
              "/R=0");

  DlgAddCtrl( dlg,
              DLG_PushButton,
              "&Help",
              Dlg_PosOffset + Dlg_StanBtnWIdth + 31,
              DLG_PosOffset,
              Dlg_StanBtnWidth,
              0,
              1005,
              0,
              "/R=2");

  if (DlgExecute( dlg, 1003, "Edit Keystrokes", "", "", 0)) {
    tof;
    key_buf = "";
    while (!at_eof) {
      rs.message = parse_int("MSG=",get_line);
      rs.paraml = parse_int("PARAML=",get_line);
      rs.paramh = parse_int("PARAMH=",get_line);
      rs.time = parse_int("TIME=",get_line);

      struct_to_Str(tstr,rs);
      key_buf += tstr;
      down;
    }
  } else {
    key_buf = t_key_buf;
  }

  DlgKill(Dlg);

EXIT:
/* We must double any "" characters even if we did not edit the string */
	Set_Global_Str('@KEYBUF',Key_Buf);
	RM('Double_127');
	Set_Global_Str('@KM!',convert_string(Global_Str('@KEYBUF')));

	if (Switch_Win_Id(Menu_Window)) {
    Delete_Window;
	}
	if (Switch_Win_Id(Active_Window)) {
	}
	Insert_Mode = T_Insert_Mode;
	Return_Str = T_Return_Str;
	Refresh = T_Refresh;
	Set_Global_Int('KEYMAC_EDIT_RUN',1);
}

macro KEYMAC_CHECK trans2 {
/*******************************************************************************
																MULTI-EDIT MACRO

Name:	KEYMAC_CHECK

Description: Checks for key assignment conflicts in keystroke macros.

							 (C) Copyright 1991 by American Cybernetics, Inc.
*******************************************************************************/
	int T_Refresh,
					k_int,
					M_Int,
					K_line,
					T_Reg_Exp_stat,
					K_Type,
					Choice,
					fix_flag = 0,
					Cancelled = Parse_Int('/C=',MParm_Str);
	str K_Str[30],E_Str[20],M_Str[15],T_Rec[2048];

	if (Parse_Int('/P=',Mparm_str) || Cancelled) {
		T_Refresh = Refresh;
		Refresh = False;

		T_Rec = Global_Str('@KMG#');
		Fix_Flag = 0;
		Call FIX_127;
		if ((Cancelled == 0) & (Global_Int('KEYMAC_EDIT_RUN') == 0)) {
			RM('DOUBLE_127');
		}
		K_Str = Parse_Str('D=',T_Rec);
		if (Parse_Str('D=',T_Rec) == '') {
/* Don't allow a blank description, put a default one in */
			K_Str = '(unnamed)';
		}

		Set_Global_Str('@KMG#',
			'D=' + K_Str +
      'KEY=' + Parse_Str('KEY=',T_Rec) +
			'M=' + Parse_Str('M=',T_Rec) +
			'S=' + Global_Str('@KEYBUF'));

RECHECK:
		Choice = 0;
		T_Rec = Global_Str('@KMG#');
    K_int = Parse_int('KEY=',T_Rec);
		M_int = Parse_int('M=',T_Rec);
		if (K_int > 0) {

/* First, search for a conflict in the list */
			T_Reg_Exp_Stat = Reg_exp_stat;
			Mark_Pos;
			K_Line = C_Line;
			Tof;
			Reg_exp_stat = true;

Search_AGAIN:
      if (Search_Fwd('KEY=' + Str(K_Int) + '||$',0)) {
				if (C_Line == K_Line) {
					Eol;
					Goto SEARCH_AGAIN;
				}
				K_Type = -1;
				Goto KEYSTROKE_CONFLICT;
			}
/* Next, check for a conflict in memory */
			K_Type = Inq_Key(K_Int & $FF,(K_Int >> 8) & $FF,M_Int,K_Str);
			if (K_Type) {
				M_Str = 'Ignore(KM)';
				if (K_Type == 1) {
					E_Str = 'macro.';
				} else if (K_Type == 2) {
KEYSTROKE_CONFLICT:
					E_Str = 'keystroke macro.';
					M_Str = 'Replace(KM)';
				} else {
					E_Str = 'command.';
				}
				RM('SETUP^MAKEKEY /K1=' + Str(K_Int & $FF) + '/K2=' +
					Str((K_Int >> 8) & $FF));
				RM('MEERROR^Beeps /C=1');
    //    Put_Box(15,5,55,10,0,M_B_Color,'WARNING',True);
    //    Write('The Key: ' + Return_Str + ' is already',17,6,0,M_B_Color);
    //    Write('assigned to a ' + E_Str,17,7,0,M_B_Color);
				RM('USERIN^XMENU /T=0/X=17/Y=8/S=1/M=Assign different key(KM)Cancel()'
					+ M_Str);
				Choice = Return_Int;
				if (Choice == 1) {
					RM('KEYMAC^KEYMAC_K_PROMPT /T=ENTER A NEW KEY ASSIGNMENT/X=20/Y=7');
					Fix_Flag = 0;
					Call FIX_127;
					Set_Global_Str('@KMG#','D=' + Parse_Str('D=',T_Rec) +
           'KEY=' + Str(Return_Int)+
						'M=' + Str(M_Int) + 'S=' + Global_Str('@KEYBUF'));

				} else if (Choice == 3) {
					if (K_Type == -1) {
/* Erase the conflicting keystroke.  Leave the new one intact. */
						Fix_Flag = 1;
						Call FIX_127;
						Put_Line('D=' + Parse_Str('D=',Get_Line) +
							'M=' + Parse_Str('M=',Get_Line) +
							'S=' + Global_Str('@KEYBUF'));

						Set_Global_Int('@DB_NEED_REBUILD!',1);
					}
				} else {
					Fix_Flag = 0;
					Call FIX_127;
					Set_Global_Str('@KMG#','D=' + Parse_Str('D=',T_Rec) +
						'M=' + Str(M_Int) + 'S=' + Global_Str('@KEYBUF'));
				}
      //  Kill_Box;
			}

			Goto_Mark;
			Reg_Exp_Stat = T_Reg_exp_stat;

			if (Choice == 1) {
				Goto RECHECK;
			}

		}

		Refresh = T_Refresh;
	}
	Goto EXIT;

FIX_127:
	if (Fix_Flag) {
		Fix_Flag = XPos('S=',Get_Line,1);
		if (Fix_Flag) {
			Set_Global_Str('@KEYBUF',Copy(Get_Line,Fix_Flag + 3,2048));
		}
	} else {
		Fix_Flag = XPos('S=',T_Rec,1);
		if (Fix_Flag) {
			Set_Global_Str('@KEYBUF',Copy(T_Rec,Fix_Flag + 3,2048));
		}
	}
	if (Fix_Flag == 0) {
		Set_Global_Str('@KEYBUF','');
	}
	Fix_Flag = 0;
	RET;

EXIT:
	Set_Global_Int('KEYMAC_EDIT_RUN',0);
	Set_Global_Str('@KEYBUF','');
	Return_Int = 1;

}

macro DOUBLE_127 trans2 {
/*******************************************************************************
																MULTI-EDIT MACRO

Name:	DOUBLE_127

Description: Finds any ASCII 127 '' characters in a keystroke macro data
						 string and doubles it so it may be stored in .DB format.

							 (C) Copyright 1991 by American Cybernetics, Inc.
*******************************************************************************/
	str Buffer[2048];
	int K_Int;

	Buffer = Global_Str('@KEYBUF');
	K_Int = -1;
LOOP:
	K_Int = XPos('|127',Buffer,K_Int + 2);
	if (K_Int) {
		Buffer = Str_Ins('|127',Buffer,K_Int);
		Goto LOOP;
	}
	Set_Global_Str('@KEYBUF',Buffer);

}

macro KEYMAC_ADD_TEMP trans2 {
/*******************************************************************************
																MULTI-EDIT MACRO

Name:	KEYMAC_ADD_TEMP

Description: Allows user to save a temporary keystroke macros permanently.

							 (C) Copyright 1991 by American Cybernetics, Inc.
*******************************************************************************/
	int Amount = Global_Int('!KMTRANS_COUNT'),Active_Window = Window_Id,
					T_Refresh = Refresh,Count = 0,
					T_Key;

	Refresh = False;
	if (Amount < 1) {
		Goto EXIT;
	}
	Create_Window;
	while (Count < Amount) {
		++Count;
		t_key = global_Int('!KMTRANS_KEY' + str(Count));
		RM('SETUP^MAKEKEY /K1=' + Str(T_Key & 0xFF)
			 + '/K2=' + Str((T_Key >> 8) & 0xFF));
		Put_Line(Return_Str);
		Down;
	}
	Tof;
	Set_Global_Str('KMEIPARM_1', '/TP=15/L=1/C=2/MW=29/WIN=' + str(cur_window));
	RM('USERIN^DATA_IN /A=2/DC=1/PRE=KME/#=1/T=SELECT TEMPORARY MACRO TO SAVE/H=/S=1');
	if (Return_Int == 1) {
		Count = C_Line;
		t_key = global_Int('!KMTRANS_KEY' + str(Count));
		RM('SETUP^MAKEKEY /K1=' + Str(T_Key & 0xFF)
			 + '/K2=' + Str((T_Key >> 8) & 0xFF));
		Set_Global_Str('@KEYBUF',Global_Str('!KMTRANS_BUF' + str(Count)));
		RM('KEYMAC^KEYMAC_LOAD /KW=1/LM=1/M=' + Str(Mode) + '/D=' + Return_Str +
				'/K=' + Str(global_Int('!KMTRANS_KEY' + str(Count))));

/* Get rid of the formerly temporary keystroke macro from the list */
		Return_int = count;
		RM("DELETEITEM /G=!KMTRANS_BUF/T=0/#=" + Str(amount));
		Return_int = count;
		RM("DELETEITEM /G=!KMTRANS_KEY/T=1/#=" + Str(amount));
		Set_Global_Int('!KMTRANS_COUNT',amount - 1);

	}
	Delete_Window;
EXIT:
	Switch_Win_Id(Active_Window);
	Refresh = T_Refresh;
}


int KEYMAC_K_PROMPT (str title = parse_str ("/T=", mparm_str),
    int k1 = parse_int("/K1=",mparm_str), k2 = parse_int("/K2=",mparm_str)) {
/*******************************************************************************
																MULTI-EDIT MACRO

Name:	KEYMAC_K_PROMPT

Description: Provides a prompt for a keystroke for keystroke macro editing.

							 (C) Copyright 1991 by American Cybernetics, Inc.
*******************************************************************************/
  int dlg;
  DlgCreate (dlg);

  DlgAddCtrl (dlg, DLG_Static, "Keycode:", 1, 1, 30, 0, 2000, 0, "");
  DlgAddCtrl (dlg, DLG_Keycode, "", Dlg_PosOffset, Dlg_PosOffset + 1, 30, 0, 2001, 0, "");
  DlgSetStr(dlg, 2001, "/K1=" + str(k1) + "/K2=" + str(k2));
  DlgAddCtrl (dlg, DLG_PushButton, "OK",     DLG_PosOffset, DLG_PosOffset + 2, DLG_StanBtnWidth, 0, 2002, DLGF_DefButton, "/R=1");
  DlgAddCtrl (dlg, DLG_PushButton, "Cancel", DLG_PosOffset + DLG_StanBtnWidth + 2, DLG_PosOffset, DLG_StanBtnWidth, 0, 2003, 0, "/R=0");
  DlgAddCtrl (dlg, DLG_PushButton, "&Help", DLG_PosOffset + DLG_StanBtnWidth + 3, DLG_PosOffset, DLG_StanBtnWidth, 0, 2004, 0, "/R=2");

  int result = DlgExecute (dlg, 2001, title, "Keystroke Macros", "", 0);

  str kstr = DlgGetStr (dlg, 2001);

  return_int = parse_int ("/K1=", kstr) | (parse_int ("/K2=", kstr) << 8);
  return_str = parse_str ("/KL=", kstr);
  Return(result);
}

/********************************MULTI-EDIT MACRO******************************

Name: MakeKeyMac

Description:  Takes the keystroke macro information and puts it into
	a global variable.

							 (C) Copyright 1991 by American Cybernetics, Inc.
*******************************************************************************/
macro MakeKeyMac trans2 {

  int dlg;

  DlgCreate (dlg);

  DlgAddCtrl (dlg, DLG_PushButton, "Save &Permanant", 1, 1, 0, 0, 2100, DLGF_DefButton, "/R=10");
  DlgAddCtrl (dlg, DLG_PushButton, "Current &Session Only", DLG_PosOffset + 20, 1, 0, 0, 2101, 0, "/R=11");
  DlgAddCtrl (dlg, DLG_PushButton, "Cancel", DLG_PosOffset + 30, 1, 0, 0, 2103, 0, "/R=0");
  int result = DlgExecute (dlg, 2100, "Macro Recorded", "", "", 0);

  if (result == 10) {
/* Add the macro to the list */
    Set_Global_Str('@KEYBUF', Get_Record_Buffer);
    RM('KEYMAC_LOAD /KW=1/LM=1/D=(unnamed)');
//    Push_Key(0,61);
//    Push_Key(0,79);       abcdef
    RM('KEYMAC_LIST');
  } else if (Result == 11) {
    RM('KEYMAC^KEYMAC_K_PROMPT /T=Define Key Assignment');
    int count =  global_int('!KMTRANS_COUNT') + 1;
    set_global_int  ('!KMTRANS_COUNT', Count);
    set_global_str  ('!KMTRANS_BUF' + str(Count), Get_Record_Buffer);
    set_global_int  ('!KMTRANS_KEY' + str(Count), Return_Int);
    global_to_key   (Return_Int, '!KMTRANS_BUF' + str(Count), Mode);
/*
RM("DUMP_KEYBUF /G=!KMTRANS_BUF" + str(count));
*/
  }
	Update_Status_Line;
EXIT:
}

void Dump_keybuf ()
{
  str t [2048] = global_str(parse_Str("/G=",mparm_str));
  struct TEventMsg rs;
  refresh = false;
  RM ('CREATEWINDOW');
  tof;
  int l = length (t);

  while (l > 0 ) {

    str_to_struct (rs, t);

    put_line ("Message= " + hex_str (rs.message) +
                      " Param= " + hex_str (rs.ParamL + (rs.ParamH << 16)) +
                      " Time= " +  hex_str (rs.time)
                      );

    t = Copy (t, 11, l - 10);
    l = Length (t);
    down;

  }
  refresh = true;
  file_changed = False;
  redraw;

}