/****************************************************
 * vt100 emulator - window/keyboard support
 *
 *	v2.6 870227 DBW - bug fixes for all the stuff in v2.5
 *	v2.5 870214 DBW - more additions (see readme file)
 *	v2.4 861214 DBW - lots of fixes/additions (see readme file)
 *	v2.3 861101 DBW - minor bug fixes
 *	v2.2 861012 DBW - more of the same
 *	v2.1 860915 DBW - new features (see README)
 *	     860823 DBW - Integrated and rewrote lots of code
 *	v2.0 860809 DBW - Major rewrite
 *	v1.1 860720 DBW	- Switches, 80 cols, colors, bug fixes
 *	v1.0 860712 DBW	- First version released
 *
 ****************************************************/

#include "vt100.h"

/* keyboard definitions for toasc() */
static char keys[75] = {
    '`','1','2','3','4','5','6','7','8','9','0','-' ,
    '=','\\', 0, '0','q','w','e','r','t','y','u','i','o' ,
    'p','[',']', 0, '1','2','3','a','s','d','f','g','h' ,
    'j','k','l',';','\'', 0, 0, '4','5','6', 0, 'z','x','c','v',
    'b','n','m',44,'.','/', 0, '.','7','8','9',' ',8,
    '\t',13,13,27,127,0,0,0,'-' } ;

/***************************************************
 *  function to swap the use of backspace and delete
 ***************************************************/

void swap_bs_del()
    {
    if (p_bs_del)   p_bs_del = 0;
    else	    p_bs_del = 1;

    keys[0x41] =    p_bs_del ? 127 : 8;
    keys[0x46] =    p_bs_del ? 8 : 127;
    }

/*************************************************
 *  function to get file name (via a requestor)
 *************************************************/
void req(prmpt,name,getinp)
char *prmpt,*name;
int  getinp;
    {
    ULONG class;
    unsigned int code, qual;
    struct IntuiMessage *Msg;

    /* Make sure the prompt gets updated */
    if (numreqs == 1 && strcmp(Prompt,prmpt) != 0) {
	EndRequest(&myrequest,mywindow);
	numreqs = 0;
	}

    /* copy in a prompt and a default */
    strcpy(Prompt,prmpt);
    strcpy(InpBuf,name);

    /* If there is a requester... reuse it */
    if (numreqs == 1) RefreshGadgets(&mystrgad,mywindow,&myrequest);

    /* otherwise create it */
    else {
	if (Request(&myrequest,mywindow) == 0) {
	    emits("ERROR - CAN'T CREATE REQUESTOR FOR:\n");
	    emits(Prompt); emit('\n');
	    emits(InpBuf); emit('\n');
	    return;
	    }
	else numreqs = 1;
	}

    /* if we don't want input, we're done */
    if (getinp == 0 || numreqs == 0) return;

    /* throw away any extra messages */
    Wait(1L << mywindow->UserPort->mp_SigBit);
    while (Msg = (struct IntuiMessage *)GetMsg(mywindow->UserPort))
	ReplyMsg(Msg);

    /* here is where we pre-select the gadget   */
    if (!ActivateGadget(&mystrgad,mywindow,&myrequest)) {

	/* wait for his/her hands to get off the keyboard (Amiga-key) */
	Delay(20L);
	while (Msg = (struct IntuiMessage *)GetMsg(mywindow->UserPort))
	    ReplyMsg(Msg);

	/* try once more before giving up... */
	ActivateGadget(&mystrgad,mywindow,&myrequest);
	}

    /* wait for input to show up */
    while (1) {
	if ((NewMessage = (struct IntuiMessage *)
		GetMsg(mywindow->UserPort)) == FALSE) {
	    Wait(1L<<mywindow->UserPort->mp_SigBit);
	    continue;
	    }
	class = NewMessage->Class;
	code  = NewMessage->Code;
	qual  = NewMessage->Qualifier;
	ReplyMsg(NewMessage);

	/* the requestor got terminated... yea!! */
	if (class == REQCLEAR) break;

	/* maybe this is a menu item to handle */
	if (class == MENUPICK) handle_menupick(class,code);
	}

    /* all done, so return the result */
    numreqs = 0;
    strcpy(name,InpBuf);
    }

/*************************************************
*  function to print a string
*************************************************/
void emits(string)
char string[];
    {
    int i;
    char c;

    i=0;
    while (string[i] != 0)
	{
	c=string[i];
	if (c == 10) emit(13);
	emit(c);
	i += 1;
	}
    }

/*************************************************
*  function to output ascii chars to window
*************************************************/
void emit(c)
char c;
    {
    static char wrap_flag = 0;	/* are we at column 80? */

    c &= 0x7F;
    switch( c )
	{
	case '\t':
	x += 64 - ((x-MINX) % 64);
	break;

	case 10:  /* lf */
	y += 8;
	break;

	case 13:  /* cr */
	x = MINX;
	break;

	case 8:   /* backspace */
	x -= 8;
	if (x < MINX) x = MINX;
	break;

	case 12:     /* page */
	x = MINX;
	y = MINY;
	SetAPen(mywindow->RPort,0L);
	RectFill(mywindow->RPort,(long)MINX,
	    (long)(MINY-7),(long)(MAXX+7),(long)(MAXY+1));
	SetAPen(mywindow->RPort,1L);
	break;

	case 7:     /* bell */
	if (p_volume == 0) DisplayBeep(NULL);
	else {
	    BeginIO(&Audio_Request);
	    WaitIO(&Audio_Request);
	    }
	break;

	default:
	if (c < ' ' || c > '~') break;
	if (p_wrap && wrap_flag && x >= MAXX) {
	    x = MINX;
	    y += 8;
	    if (y > MAXY) {
		y = MAXY;
		ScrollRaster(mywindow->RPort,0L,8L,(long)MINX,
		    (long)(MINY-6),(long)(MAXX+7),(long)(MAXY+1));
		}
	    }
	Move(mywindow->RPort,(long)x,(long)y);

	if (curmode&FSF_BOLD) {
	    if (p_depth > 1) {
		SetAPen(mywindow->RPort,(long)(2+(1^p_screen)));
		SetSoftStyle(mywindow->RPort,(long)curmode,253L);
		}
	    else SetSoftStyle(mywindow->RPort,(long)curmode,255L);
	    }
	else SetSoftStyle(mywindow->RPort,(long)curmode,255L);

	if (curmode&FSF_REVERSE) {
	    SetDrMd(mywindow->RPort,(long)(JAM2+INVERSVID));
	    Text(mywindow->RPort,&c,1L);
	    SetDrMd(mywindow->RPort,(long)JAM2);
	    }
	else Text(mywindow->RPort,&c,1L);

	if (curmode&FSF_BOLD) SetAPen(mywindow->RPort,1L);
	x += 8;
	} /* end of switch */

    if (y > MAXY) {
	y = MAXY;
	x = MINX;
	ScrollRaster(mywindow->RPort,0L,8L,(long)MINX,
	    (long)(MINY-6),(long)(MAXX+7),(long)(MAXY+1));
	}
    if (x > MAXX) {
	wrap_flag = 1;
	x = MAXX;
	}
    else wrap_flag = 0;
    }

/*************************************************
*  function to output ascii chars to window (batched)
*************************************************/
void emitbatch(la,lookahead)
int la;
char *lookahead;
    {
    int i;	

    Move(mywindow->RPort,(long)x,(long)y);
    i = x / 8;
    if (i+la >= maxcol) {
	if (p_wrap == 0) la = maxcol - i;
	else {
	    lookahead[la] = 0;
	    emits(lookahead);
	    return;
	    }
	}
    if (curmode&FSF_BOLD) {
	if (p_depth > 1) {
	    SetAPen(mywindow->RPort,(long)(2+(1^p_screen)));
	    SetSoftStyle(mywindow->RPort,(long)curmode,253L);
	    }
	else SetSoftStyle(mywindow->RPort,(long)curmode,255L);
	}
    else SetSoftStyle(mywindow->RPort,(long)curmode,255L);

    if (curmode&FSF_REVERSE) {
	SetDrMd(mywindow->RPort,(long)(JAM2+INVERSVID));
	Text(mywindow->RPort,lookahead,(long)la);
	SetDrMd(mywindow->RPort,(long)JAM2);
	}
    else Text(mywindow->RPort,lookahead,(long)la);
    if (curmode&FSF_BOLD) SetAPen(mywindow->RPort,1L);
    x += (8 * la);
    }

/******************************
* Manipulate cursor
******************************/
void cursorflip()
    {
    SetDrMd(mywindow->RPort,(long)COMPLEMENT);
    SetAPen(mywindow->RPort,3L);
    RectFill(mywindow->RPort,
	(long)(x-1),(long)(y-6),(long)(x+8),(long)(y+1));
    SetAPen(mywindow->RPort,1L);
    SetDrMd(mywindow->RPort,(long)JAM2);
    }

/************************************************
*  function to take raw key data and convert it 
*  into ascii chars
**************************************************/
int toasc(code,qual,local)
unsigned int code,qual;
int local;
    {
    unsigned int ctrl,shift,capsl,amiga,alt;
    char c = 0, keypad = 0;
    char *ptr;

    ctrl    = qual & IEQUALIFIER_CONTROL;
    capsl   = qual & IEQUALIFIER_CAPSLOCK;
    amiga   = qual & (IEQUALIFIER_LCOMMAND | IEQUALIFIER_RCOMMAND);
    shift   = qual & (IEQUALIFIER_LSHIFT   | IEQUALIFIER_RSHIFT);
    alt	    = qual & (IEQUALIFIER_LALT     | IEQUALIFIER_RALT);

    switch ( code )
	{
	case 98:
	case 226:
	case 99:
	case 227:
	case 96:
	case 97:
	case 224:
	case 225:
	case 100:
	case 101:
	case 228:
        case 229:
	case 102:
	case 103:
	case 230:
	case 231:   c = 0; break; /* ctrl, shift, capsl, amiga, or alt */

	case 0x50: 
	case 0x51: 
	case 0x52: 
	case 0x53: 
	case 0x54: 
	case 0x55: 
	case 0x56: 
	case 0x57: 
	case 0x58: 
	case 0x59:  c = 0;
		    if (shift)	ptr = p_F[code - 0x50];
		    else	ptr = p_f[code - 0x50];
		    if (!script_on && *ptr == p_keyscript)
			    script_start(++ptr);
		    else    sendstring(ptr);
		    break;
	case 0x0f: c = (p_keyapp) ? 'p' : '0'; keypad = TRUE; break;
	case 0x1d: c = (p_keyapp) ? 'q' : '1'; keypad = TRUE; break;
	case 0x1e: c = (p_keyapp) ? 'r' : '2'; keypad = TRUE; break;
	case 0x1f: c = (p_keyapp) ? 's' : '3'; keypad = TRUE; break;
	case 0x2d: c = (p_keyapp) ? 't' : '4'; keypad = TRUE; break;
	case 0x2e: c = (p_keyapp) ? 'u' : '5'; keypad = TRUE; break;
	case 0x2f: c = (p_keyapp) ? 'v' : '6'; keypad = TRUE; break;
	case 0x3d: c = (p_keyapp) ? 'w' : '7'; keypad = TRUE; break;
	case 0x3e: c = (p_keyapp) ? 'x' : '8'; keypad = TRUE; break;
	case 0x3f: c = (p_keyapp) ? 'y' : '9'; keypad = TRUE; break;
	case 0x43: c = (p_keyapp) ? 'M' : 13 ; keypad = TRUE; break;
	case 0x4a: c = (p_keyapp) ? 'l' : '-'; keypad = TRUE; break;
	case 0x5f: sendstring("\033Om") ;break;
	case 0x3c: c = (p_keyapp) ? 'n' : '.'; keypad = TRUE; break;
	case 0x4c:
	case 0x4d: 
	case 0x4e: 
	case 0x4f: sendchar(27);            /* cursor keys */
		   if (p_curapp) sendchar('O');
		   else sendchar('[');
		   sendchar(code - 11);
		   break;

	default:
	if (code < 75) c = keys[code];
	else c = 0;
	}

    if (keypad) {
        if (p_keyapp) sendstring("\033O");
        sendchar(c);
        return(0);
	}
        
    /* add modifiers to the keys */

    if (c != 0) {
	if (shift) {
	    if ((c <= 'z') && (c >= 'a')) c -= 32;
	    else
	    switch( c ) {
		case '[':  c = '{'; break;
		case ']':  c = '}'; break;
		case '\\': c = '|'; break;
		case '\'': c = '"'; break;
		case ';':  c = ':'; break;
		case '/':  c = '?'; break;
		case '.':  c = '>'; break;
		case ',':  c = '<'; break;
		case '`':  c = '~'; break;
		case '=':  c = '+'; break;
		case '-':  c = '_'; break;
		case '1':  c = '!'; break;
		case '2':  c = '@'; break;
		case '3':  c = '#'; break;
		case '4':  c = '$'; break;
		case '5':  c = '%'; break;
		case '6':  c = '^'; break;
		case '7':  c = '&'; break;
		case '8':  c = '*'; break;
		case '9':  c = '('; break;
		case '0':  c = ')'; break;
		default:            break;
		}
	    }
	else if (capsl && (c <= 'z') && (c >= 'a')) c -= 32;
	}
    if (ctrl) {
	if (c > '`' && c <= 127) c -= 96;
	else if (c > '@' && c <= '_') c -= 64;
	else if (c == '6') c = 30;
	else if (c == '-' || c == '?') c = 31;
	}
    if (ctrl && (c == '@' || c == '2' || c == ' ')) {
	if (!local) sendchar(alt?128:0);
	c = 0;
	}
    else if (c != 0 && (!local)) sendchar(alt?c+128:c);
    return((int)c);
    }

