/****************************************************
 * vt100 emulator - window/keyboard support
 *
 *	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
 *
 ****************************************************/

#define MODULE_WINDOW 1
#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,'-' } ;

/* forward declarations for LATTICE */
void filename();
void emits();
void emit();
void emitbatch();
void cursorflip();

/*************************************************
*  function to get file name
*************************************************/
void filename(name)
char name[];
    {
    char c;
    ULONG class;
    unsigned int code;
    int keepgoing,i;
    keepgoing = TRUE;
    i=0;
    while (keepgoing) {
	while( NewMessage=(struct IntuiMessage *)GetMsg(mywindow->UserPort) )
	    {
	    class = NewMessage->Class;
	    code = NewMessage->Code;
	    ReplyMsg( NewMessage );
	    if (class==RAWKEY)
		{
		c = toasc(code,1);
		name[i]=c;
		if (name[i] != 0)
		    {
		    if (name[i] == 13)
			{
			name[i]=0;
			keepgoing = FALSE;
			}
		    else
			{
			if (name[i] == 8 || name[i] == 127)
			    {
			    i -= 2;
			    if (i < -1)  i = -1;
			    else {
				if (x == MINX) { y -= 8; x = MAXX; }
				emit(8);
				emit(32);
				emit(8);
				}
			    }
			else
			emit(c);
			if (x == MAXX) emits("\n");
			}
		    i += 1;
		    }
		}
	    } /* end of new message loop */
	}   /* end of god knows what */
    emit(13);
    emit(10);
    } /* end of function */


/*************************************************
*  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,local)
unsigned int code;
int local;
    {
    static int ctrl = 0;
    static int shift = 0;
    static int capsl = 0;
/*  static int amiga = 0; */
    static int meta  = 0;
    char c = 0, keypad = 0;
    char *ptr;

    switch ( code )
	{
	case 98:   capsl = 1; c = 0;break;
	case 226:  capsl = 0; c = 0;break;
	case 99:   ctrl  = 1; c = 0;break;
	case 227:  ctrl  = 0; c = 0;break;
	case 96:
	case 97:   if(++shift > 2) shift = 0; c = 0; break;
	case 224:
	case 225:  if (--shift < 0) shift = 0; c = 0;break;
	case 100:
	case 101:  if (++meta > 2) meta = 0; c = 0; break;
	case 228:
        case 229:  if (--meta < 0) meta = 0; c = 0; break;
/*

	case 102:
	case 103:  if (++amiga > 2) amiga = 0; c = 0; break;
	case 230:
	case 231:  if (--amiga < 0) amiga = 0; c = 0; break;
*/
	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 = (keyapp) ? 'p' : '0'; keypad = TRUE; break;
	case 0x1d: c = (keyapp) ? 'q' : '1'; keypad = TRUE; break;
	case 0x1e: c = (keyapp) ? 'r' : '2'; keypad = TRUE; break;
	case 0x1f: c = (keyapp) ? 's' : '3'; keypad = TRUE; break;
	case 0x2d: c = (keyapp) ? 't' : '4'; keypad = TRUE; break;
	case 0x2e: c = (keyapp) ? 'u' : '5'; keypad = TRUE; break;
	case 0x2f: c = (keyapp) ? 'v' : '6'; keypad = TRUE; break;
	case 0x3d: c = (keyapp) ? 'w' : '7'; keypad = TRUE; break;
	case 0x3e: c = (keyapp) ? 'x' : '8'; keypad = TRUE; break;
	case 0x3f: c = (keyapp) ? 'y' : '9'; keypad = TRUE; break;
	case 0x43: c = (keyapp) ? 'M' : 13 ; keypad = TRUE; break;
	case 0x4a: c = (keyapp) ? 'l' : '-'; keypad = TRUE; break;
	case 0x5f: sendstring("\033Om") ;break;
	case 0x3c: c = (keyapp) ? 'n' : '.'; keypad = TRUE; break;
	case 0x4c:
	case 0x4d: 
	case 0x4e: 
	case 0x4f: sendchar(27);            /* cursor keys */
		   if (curapp) sendchar('O');
		   else sendchar('[');
		   sendchar(code - 11);
		   break;

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

    if (keypad) {
        if (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 (amiga && c == '.') {
	if (!local) sendbreak();
	c = 0;
	}
    else
*/
    if (ctrl && (c == '@' || c == '2' || c == ' ')) {
	if (!local) sendchar(meta?128:0);
	c = 0;
	}
    else if (c != 0 && (!local)) sendchar(meta?c+128:c);
    return((int)c);
    }
