home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 1: Amiga
/
FrozenFish-Apr94.iso
/
bbs
/
alib
/
d1xx
/
d114
/
vt100.lha
/
Vt100
/
window.c
< prev
next >
Wrap
C/C++ Source or Header
|
1987-11-22
|
17KB
|
649 lines
/****************************************************
* vt100 emulator - window/keyboard support
*
* v2.7 870825 ACS - Provide an info/status window rather than using
* req(). Better error handling.
* 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,'-' } ;
/* For InfoMsg...may be changed by a NEWSIZE msg in vt100.c */
int reqminx, /* Min value for x in reqwindow (pixels) */
reqmaxx, /* Max value for x in reqwindow (pixels) */
reqmaxlen, /* Max # chars in reqwindow */
reqminy, /* Min value for y in reqwindow (scan lines) */
reqmaxy, /* Max value for y in reqwindow (scan lines) */
reqfudge; /* Clear space between border and start of 1st char */
int reqy; /* Current pixel location in reqwindow */
void ReqNewSize(), OpenReqWindow();
/***************************************************
* 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;
USHORT position, RemoveGadget();
unsigned int code, qual;
int lprmpt, lname;
struct IntuiMessage *Msg;
if(reqwinup == 0)
OpenReqWindow();
if(!getinp) {
InfoMsg2Line(prmpt, name);
return;
}
lprmpt = strlen(prmpt);
lname = strlen(name);
/* Don't use strings longer than what we've provided space for. */
if(lprmpt > (MAXGADSTR-1)) {
emits("Prompt too long - truncated.\n");
lprmpt = MAXGADSTR-1;
}
if(lname > (MAXGADSTR-1)) {
emits("Name too long - truncated.\n");
lname = MAXGADSTR-1;
}
if (Msg = (struct IntuiMessage *)GetMsg(reqwindow->UserPort)) {
class = Msg->Class;
ReplyMsg(Msg);
if(class == REQCLEAR)
numreqs = 0;
if(class == NEWSIZE)
ReqNewSize(reqwindow->Height, reqwindow->Width);
}
/* Make sure the prompt gets updated */
if (numreqs == 1 && strcmp(Prompt,prmpt) != 0) {
EndRequest(&myrequest,reqwindow);
do {
Wait(1L << reqwindow->UserPort->mp_SigBit);
while (Msg = (struct IntuiMessage *)GetMsg(reqwindow->UserPort)) {
class = Msg->Class;
ReplyMsg(Msg);
if(class == NEWSIZE)
ReqNewSize(reqwindow->Height, reqwindow->Width);
}
} while (class != REQCLEAR);
numreqs = 0;
}
/* copy in a prompt and a default */
strncpy(Prompt,prmpt,lprmpt); Prompt[lprmpt+1] = '\0';
strncpy(InpBuf,name,lname); InpBuf[lname+1] = '\0';
if (numreqs == 1) { /* If there is a requester... reuse it */
RefreshGadgets(&mystrgad, reqwindow, &myrequest);
Delay(2L);
}
else { /* otherwise create it */
while(numreqs != 1) {
if (Request(&myrequest, reqwindow) == 0) {
emits("ERROR - CAN'T CREATE REQUESTOR FOR:\n");
emits(Prompt); emit('\n'); emits(InpBuf); emit('\n');
return;
}
else numreqs = 1;
do {
Wait(1L << reqwindow->UserPort->mp_SigBit);
while (Msg = (struct IntuiMessage *)GetMsg(reqwindow->UserPort)) {
class = Msg->Class;
ReplyMsg(Msg);
if(class == REQCLEAR)
numreqs = 0;
if(class == NEWSIZE)
ReqNewSize(reqwindow->Height, reqwindow->Width);
}
} while (class != REQSET);
} /* end while numreqs != 0 */
} /* end else */
/* if we don't want input, we're done */
if (getinp == 0 || numreqs == 0) return;
if((reqwindow->Flags & WINDOWACTIVE) != WINDOWACTIVE) {
WindowToFront(reqwindow);
ActivateWindow(reqwindow);
do {
Wait(1L << reqwindow->UserPort->mp_SigBit);
while(Msg = (struct IntuiMessage *)GetMsg(reqwindow->UserPort)) {
class = Msg->Class;
ReplyMsg(Msg);
if(class == NEWSIZE)
ReqNewSize(reqwindow->Height, reqwindow->Width);
}
} while (class != ACTIVEWINDOW);
}
/* here is where we pre-select the gadget */
if (!ActivateGadget(&mystrgad,reqwindow,&myrequest)) {
/* wait for his/her hands to get off the keyboard (Amiga-key) */
Delay(20L);
while (Msg = (struct IntuiMessage *)GetMsg(reqwindow->UserPort)) {
ReplyMsg(Msg);
if(class == NEWSIZE)
ReqNewSize(reqwindow->Height, reqwindow->Width);
}
/* try once more before giving up... */
ActivateGadget(&mystrgad,reqwindow,&myrequest);
}
/* wait for input to show up */
while (1) {
if ((NewMessage = (struct IntuiMessage *)
GetMsg(reqwindow->UserPort)) == FALSE) {
Wait(1L<<reqwindow->UserPort->mp_SigBit);
continue;
}
class = NewMessage->Class;
ReplyMsg(NewMessage);
/* the requestor got terminated... yea!! */
if (class == REQCLEAR) break;
if(class == NEWSIZE)
ReqNewSize(reqwindow->Height, reqwindow->Width);
/* 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);
}
void
KillReq()
{
struct IntuiMessage *Msg;
ULONG class;
if(numreqs != 0) {
EndRequest(&myrequest,reqwindow);
do {
Wait(1L << reqwindow->UserPort->mp_SigBit);
while (Msg = (struct IntuiMessage *)GetMsg(reqwindow->UserPort)) {
class = Msg->Class;
ReplyMsg(Msg);
}
} while (class != REQCLEAR);
numreqs = 0;
}
if(reqwinup) {
/* First, clear out all pending messages */
while (Msg = (struct IntuiMessage *)GetMsg(reqwindow->UserPort)) {
class = Msg->Class;
ReplyMsg(Msg);
}
NewReqWindow.LeftEdge = reqwindow->LeftEdge; /* Remember ... */
NewReqWindow.TopEdge = reqwindow->TopEdge; /* ...where... */
NewReqWindow.Width = reqwindow->Width; /* ...the user... */
NewReqWindow.Height = reqwindow->Height; /* ...put it. */
CloseWindow(reqwindow); /* Now we can close the window */
reqwinup = 0;
}
}
void
InfoMsg2Line(header, msg)
char *header, *msg;
{
ScrollInfoMsg(1);
InfoMsgNoScroll(header);
ScrollInfoMsg(1);
InfoMsgNoScroll(msg);
ScrollInfoMsg(1);
}
void
InfoMsg1Line(msg)
char *msg;
{
ScrollInfoMsg(1);
InfoMsgNoScroll(msg);
ScrollInfoMsg(1);
}
/* Output the specified data to the "info" window */
void
ScrollInfoMsg(lines)
int lines;
{
/* ULONG class;
struct IntuiMessage *Msg; */
int pixels = lines << 3;
if(!reqwinup)
OpenReqWindow();
/* if(Msg=(struct IntuiMessage *)GetMsg(reqwindow->UserPort)) {
class = Msg->Class;
ReplyMsg(Msg);
if(class == NEWSIZE)
ReqNewSize(reqwindow->Height, reqwindow->Width);
} */
if ( (reqy += pixels) > reqmaxy) {
reqy = reqmaxy;
if(pixels > 0)
ScrollRaster(reqwindow->RPort, 0L, (LONG)pixels,
(LONG)reqminx,
(LONG)reqminy,
(LONG)(reqmaxx+7),
(LONG)(reqmaxy+7));
/* Was: (LONG)(wp->Width - wp->BorderRight),
(LONG)(wp->Height - wp->BorderBottom)); */
}
}
void
InfoMsgNoScroll(msg)
char *msg;
{
LONG msglen = strlen(msg);
if(msglen > reqmaxlen)
msglen = reqmaxlen;
ScrollInfoMsg(0); /* Ensure that the msg willbe visible */
/* Position the pen at the baseline of the character (7 scan lines
** into it). */
Move(reqwindow->RPort, (LONG)reqminx, (LONG)(reqy+6));
Text(reqwindow->RPort, msg, msglen);
}
void
ReqNewSize(height, width)
SHORT height, width;
{
register struct Window *wp = reqwindow;
int oldmaxy;
/* Compute min and max for x and y coordinates. Note that for y the
** value is for the *top* of the character, not the baseline. Text()
** uses a baseline value and so it must be adjusted prior to the call
** (characters are assumed to occupy an 8x8 matrix with the baseline at
** 7). When computing the max values, calculate them so that we will
** sufficient room for an entire character. */
oldmaxy = reqmaxy;
reqminy = wp->BorderTop + reqfudge;
reqmaxy = (((height - reqminy - wp->BorderBottom) >> 3) << 3)
+ (reqminy-8);
reqminx = wp->BorderLeft + reqfudge;
reqmaxx = (((width - reqminx - wp->BorderRight) >> 3) << 3)
+ (reqminx-8);
reqmaxlen = (reqmaxx+7) / 8;
if(oldmaxy > reqmaxy) { /* Clean up the bottom of the window */
int temp = height - wp->BorderBottom - reqmaxy;
ScrollRaster(wp->RPort, 0L, (LONG)temp,
(LONG)reqminx,
(LONG)reqmaxy,
(LONG)(width - wp->BorderRight),
(LONG)(height - wp->BorderBottom));
}
}
void
OpenReqWindow()
{
struct IntuiMessage *Msg;
ULONG class;
void ReqNewSize();
reqwindow = OpenWindow(&NewReqWindow);
do {
Wait(1L << reqwindow->UserPort->mp_SigBit);
while(Msg = (struct IntuiMessage *)GetMsg(reqwindow->UserPort)) {
class = Msg->Class;
ReplyMsg(Msg);
}
} while (class != ACTIVEWINDOW);
reqfudge = 0; /* Leave 0 pixels/scan lines between border and char */
ReqNewSize(reqwindow->Height, reqwindow->Width);
reqy = reqminy; /* Top of character set by ReqNewSize() */
reqwinup = 1;
}