home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gold Fish 1
/
GoldFishApril1994_CD2.img
/
d4xx
/
d439
/
curses
/
src
/
curses.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-01-17
|
45KB
|
1,735 lines
/*
*
* Module : curses.c
*
* Description : AMIGA CURSES package.
*
* Author : Simon Raybould (sie@fulcrum.bt.co.uk)
*
* Date V1.00a : 16th February 1990
* V1.10 : 30th July 1990
* V1.20a : 4th October 1990
* V1.20 : 7th November 1990
* V1.21 : 2nd December 1990 minor fixes
* V1.22 : 7th January 1991 bug fixes
*
*/
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <intuition/screens.h>
#include <exec/types.h>
#include <exec/memory.h>
#include <devices/audio.h>
#include "acurses.h"
/* Main background screen */
static struct NewScreen NewScreen = {
0, /* LeftEdge */
0, /* TopEdge */
0, /* Width */
0, /* Height */
4, /* No. Bitplanes */
0, 1, /* DetailPen, BlockPen */
HIRES, /* ViewModes */
CUSTOMSCREEN, /* Screen type */
(struct TextAttr *)NULL, /* default font */
"Curses screen", /* Screen Title */
(struct Gadget *)NULL, /* Gadget list */
(struct BitMap *)NULL /* custom bitmap */
};
/* Main background window */
static struct NewWindow NewWindow = {
0, /* Left edge */
0, /* Top edge */
0, /* Width */
0, /* Height */
-1, -1, /* Pens */
RAWKEY, /* IDCMP flags */
ACTIVATE | BORDERLESS, /* Window flags */
NULL, /* First gadget */
NULL, /* Image data */
NULL, /* Title */
NULL, /* Pointer to screen structure */
NULL, /* Super BitMap ? */
0,0,0,0, /* MIN/MAX sizing */
CUSTOMSCREEN /* Type of screen */
};
/*
* Make author appear when right mouse button is pressed.
*/
static struct Menu _CursesMenu = {
NULL, 0, 0, 0, 0, 0,
" AMIGA CURSES by Simon J Raybould (sie@fulcrum.bt.co.uk) V1.22 07.Jan.1991",
NULL, 0, 0, 0, 0
};
/*
* Should initialise all of these to NULL to be certain that
* CleanExit() will function correctly. Most compilers will do this
* anyway, but better safe than GURUed.
*/
struct IntuitionBase *IntuitionBase = NULL;
struct GfxBase *GfxBase = NULL;
struct ConsoleDevice *ConsoleDevice = NULL;
static struct IOStdReq ioreq;
static struct Screen *CursesScreen = NULL;
static struct Window *CursesWindow = NULL;
static struct RastPort *RPort;
static struct ViewPort *VPort;
static unsigned char CursesFlags; /* Global flags */
static short CursorCol = 0,CursorLine = 0,LCursorLine = -1,LCursorCol = -1;
static struct WindowState *HeadWindowList = (struct WindowState *)NULL;
static struct RefreshElement *HeadRefreshList=(struct RefreshElement *)NULL;
static struct IOAudio *AIOptr;
static struct MsgPort *port;
static ULONG device;
static BYTE *sound_data;
static UBYTE whichannel[] = { 1, 2, 4, 8 };
/*
* void internal functions
*/
static void CleanExit(), CleanUp(), DoEcho();
static void ZapCursor(), DrawCursor();
/* Define a blank mouse pointer */
static USHORT __chip MyMsPtr[] = { 0, 0, 0, 0 };
#define NCOLOURS 32
static UWORD ColourTable[] = {
0x000, 0xfff, 0xff0, 0xf80, 0x00f, 0xf0f, 0x0ff, 0xfff,
0x620, 0xe50, 0x9f1, 0xeb0, 0x55f, 0x92f, 0x0f8, 0xccc,
0x000, 0xd22, 0x000, 0xabc, 0x444, 0x555, 0x666, 0x777,
0x888, 0x999, 0xaaa, 0xbbb, 0xccc, 0xddd, 0xeee, 0xfff
};
WINDOW *stdscr = (WINDOW *)NULL, *curscr = (WINDOW *)NULL;
int LINES=24, COLS=80; /* Defaults */
/*
* Need to be global so that flushinp() can reset them !
*/
static unsigned char GetchRPos = 0, GetchWPos = 0;
/*
* Start of code.
*/
initscr()
{
ULONG IBaseLock;
char *Ptr, *getenv();
int Tmp;
/*
* It would be devestating if someone called initscr() twice
* so make the second call fail.
*/
if(CursesFlags & CFLAG_INITSCR)
return ERR;
CursesFlags |= CFLAG_INITSCR; /* Mark that we have called initscr() */
if((IntuitionBase = (struct IntuitionBase *)
OpenLibrary("intuition.library", 0)) == NULL) {
fprintf(stderr, "Failed to open Intuition library");
CleanExit(10);
}
IBaseLock = LockIBase(0L);
NewScreen.Height = NewWindow.Height = IntuitionBase->ActiveScreen->Height;
NewScreen.Width = NewWindow.Width = IntuitionBase->ActiveScreen->Width;
UnlockIBase(IBaseLock);
/* Set interlace if height >= 400 */
if(NewScreen.Height>=400)
NewScreen.ViewModes |= LACE;
LINES = NewScreen.Height/8;
COLS = NewScreen.Width/8;
/* if LINES and/or COLS set as environment variables then use them */
if((Ptr = getenv("LINES"))) {
Tmp = atoi(Ptr);
if(Tmp>0 && Tmp<=LINES)
LINES = Tmp;
}
if((Ptr = getenv("COLS"))) {
Tmp = atoi(Ptr);
if(Tmp>0 && Tmp<=COLS)
COLS = Tmp;
}
/* Open graphics library */
if((GfxBase = (struct GfxBase *)
OpenLibrary("graphics.library", 0))==NULL) {
fprintf(stderr, "Failed to open Graphics library");
CleanExit(10);
}
/*
* must have the console.device opened to use RawKeyConvert()
*/
if(OpenDevice("console.device",-1L,(struct IORequest *)&ioreq,0L))
CleanExit(10);
ConsoleDevice=(struct ConsoleDevice *)ioreq.io_Device;
if((CursesScreen=(struct Screen *)OpenScreen(&NewScreen)) == NULL) {
fprintf(stderr, "Failed to open Screen");
CleanExit(10);
}
RPort = &(CursesScreen->RastPort);
VPort = &(CursesScreen->ViewPort);
LoadRGB4(VPort, ColourTable, NCOLOURS);
SetDrMd(RPort, JAM2);
SetAPen(RPort, 1);
NewWindow.Screen = CursesScreen; /* Must do this !! */
if((CursesWindow=(struct Window *)OpenWindow(&NewWindow)) == NULL) {
fprintf(stderr, "Failed to open Window\n");
CleanExit(10);
}
SetMenuStrip(CursesWindow, &_CursesMenu);
SetPointer(CursesWindow, MyMsPtr, 0, 0, 0, 0); /*Remove mouse pointer*/
/* Create stdscr and curscr */
stdscr = newwin(LINES, COLS, 0, 0);
curscr = newwin(LINES, COLS, 0, 0); /* used for redraws */
clearok(curscr, TRUE); /* Clear curscr on every refresh */
CursesFlags = CFLAG_ECHO | CFLAG_NLCR | CFLAG_CURSOR | CFLAG_INITSCR;
return OK;
}
/*
* Close the screen and libraries.
*/
endwin() /* called from main prior to exit. */
{
void ZapWindows();
if(!(CursesFlags & CFLAG_INITSCR)) { /* haven't called initscr() */
return ERR;
}
ZapWindows(HeadWindowList);
CleanUp();
CursesFlags &= ~CFLAG_INITSCR; /* Mark that we have called endwin() */
return OK;
}
/* Recursive routine to zap all windows and release data structures */
static void ZapWindows(WinStat)
struct WindowState *WinStat;
{
if(!WinStat)
return;
if(WinStat->Next)
ZapWindows(WinStat->Next); /* Recurse */
delwin(&WinStat->Window);
}
static void CleanExit(RetCode)
int RetCode;
{
CleanUp();
exit(RetCode);
}
static void CleanUp()
{
if(CursesWindow)
CloseWindow(CursesWindow);
if(CursesScreen)
CloseScreen(CursesScreen);
if(GfxBase)
CloseLibrary((struct Library *)GfxBase);
if(IntuitionBase)
CloseLibrary((struct Library *)IntuitionBase);
}
init_color(n, r, g, b)
short n;
unsigned char r, g, b;
{
if(n<0 || n>15 || r>1000 || g>1000 || b>1000)
return ERR;
/* If 0 then leave, else subtract 1 */
if(r) r--;
if(g) g--;
if(g) g--;
SetRGB4(VPort, n, r*16/1000, g*16/1000, b*16/1000);
return OK;
}
start_color()
{
return OK; /* No initialisation required to get colours going */
}
has_colors()
{
return TRUE; /* Yes baby we have colours on this bitch */
}
/*
* static because not implemented yet.
*/
static color_content(color, r, g, b)
short color, *r, *g, *b;
{
return OK;
}
waddstr(WinPtr, Str)
WINDOW *WinPtr;
char *Str;
{
struct WindowState *WinStat, *PWinStat = NULL;
short TmpAttrs;
if(!*Str)
return OK;
if(!(WinStat = (struct WindowState *)WinPtr->_WinStat))
return ERR;
if(WinStat->ParentWin)
if(!(PWinStat = (struct WindowState *)WinStat->ParentWin->_WinStat))
return ERR;
WinStat->LnArry[WinPtr->_cury].Touched = TRUE;
WinStat->LnArry[WinPtr->_cury].StartCol = min(WinStat->LnArry[WinPtr->_cury].StartCol, WinPtr->_curx);
if(PWinStat) {
PWinStat->LnArry[WinPtr->_cury + WinPtr->_begy].Touched = TRUE;
PWinStat->LnArry[WinPtr->_cury + WinPtr->_begy].StartCol = min(PWinStat->LnArry[WinPtr->_cury + WinPtr->_begy].StartCol, WinPtr->_curx + WinPtr->_begx);
}
while(*Str) {
switch(*Str) {
case '\t':
do {
WinStat->LnArry[WinPtr->_cury].Line[WinPtr->_curx] = ' ';
WinStat->LnArry[WinPtr->_cury].ATTRS[WinPtr->_curx++] = WinPtr->_attrs;
} while(WinPtr->_curx % 8);
break;
case '\n':
WinStat->LnArry[WinPtr->_cury].EndCol = max(WinStat->LnArry[WinPtr->_cury].EndCol, WinPtr->_curx - 1);
TmpAttrs = WinPtr->_attrs;
wattrset(WinPtr, 0); /* better to call wattrset in case I change attrs */
wclrtoeol(WinPtr);
wattrset(WinPtr, TmpAttrs);
if(PWinStat)
PWinStat->LnArry[WinPtr->_cury+WinPtr->_begy].EndCol=max(PWinStat->LnArry[WinPtr->_cury+WinPtr->_begy].EndCol,WinPtr->_curx+WinPtr->_begx-1);
WinPtr->_curx = 0;
WinPtr->_cury++;
if(WinPtr->_cury > WinStat->ScrollBot) {
if(WinPtr->_scroll)
scroll(WinPtr);
WinPtr->_cury = WinStat->ScrollBot;
}
if(*(Str + 1)) { /* If there is more then touch this line too */
WinStat->LnArry[WinPtr->_cury].Touched = TRUE;
WinStat->LnArry[WinPtr->_cury].StartCol = min(WinStat->LnArry[WinPtr->_cury].StartCol, WinPtr->_curx);
if(PWinStat) {
PWinStat->LnArry[WinPtr->_cury+WinPtr->_begy].Touched = TRUE;
PWinStat->LnArry[WinPtr->_cury+WinPtr->_begy].StartCol = min(PWinStat->LnArry[WinPtr->_cury+WinPtr->_begy].StartCol, WinPtr->_curx+WinPtr->_begx);
}
}
break;
default:
WinStat->LnArry[WinPtr->_cury].Line[WinPtr->_curx] = *Str;
WinStat->LnArry[WinPtr->_cury].ATTRS[WinPtr->_curx] = WinPtr->_attrs;
WinPtr->_curx++;
break;
}
/* If hit right edge of window then increment _cury */
if(WinPtr->_curx > WinPtr-> _maxx) {
WinStat->LnArry[WinPtr->_cury].EndCol = max(WinStat->LnArry[WinPtr->_cury].EndCol, WinPtr->_curx - 1);
WinPtr->_curx = 0;
WinPtr->_cury++;
if(WinPtr->_cury > WinStat->ScrollBot) {
if(WinPtr->_scroll)
scroll(WinPtr);
WinPtr->_cury = WinStat->ScrollBot;
}
if(WinPtr->_cury > WinPtr->_maxy)
WinPtr->_cury = WinPtr->_maxy;
if(*(Str + 1)) { /* If there is more then touch this line too */
WinStat->LnArry[WinPtr->_cury].Touched = TRUE;
WinStat->LnArry[WinPtr->_cury].StartCol = min(WinStat->LnArry[WinPtr->_cury].StartCol, WinPtr->_curx);
if(PWinStat) {
PWinStat->LnArry[WinPtr->_cury+WinPtr->_begy].Touched = TRUE;
PWinStat->LnArry[WinPtr->_cury+WinPtr->_begy].StartCol = min(PWinStat->LnArry[WinPtr->_cury+WinPtr->_begy].StartCol, WinPtr->_curx+WinPtr->_begx);
}
}
}
Str++;
}
WinStat->LnArry[WinPtr->_cury].EndCol = max(WinStat->LnArry[WinPtr->_cury].EndCol, WinPtr->_curx - 1);
if(PWinStat)
PWinStat->LnArry[WinPtr->_cury+WinPtr->_begy].EndCol = max(PWinStat->LnArry[WinPtr->_cury+WinPtr->_begy].EndCol, WinPtr->_curx+WinPtr->_begx-1);
return OK;
}
waddch(WinPtr, c)
WINDOW *WinPtr;
char c;
{
char *str = " ";
*str = c;
return waddstr(WinPtr, str);
}
winsch(WinPtr, c)
WINDOW *WinPtr;
char c;
{
int i;
struct WindowState *WinStat;
if(!(WinStat = (struct WindowState *)WinPtr->_WinStat))
return ERR;
/* shuffle line along to the right */
for (i = WinPtr->_maxx; i > WinPtr->_curx; i--)
WinStat->LnArry[WinPtr->_cury].Line[i] = WinStat->LnArry[WinPtr->_cury].Line[i-1];
WinStat->LnArry[WinPtr->_cury].Line[i] = c;
WinStat->LnArry[WinPtr->_cury].StartCol = min(WinStat->LnArry[WinPtr->_cury].StartCol, WinPtr->_curx);
WinStat->LnArry[WinPtr->_cury].EndCol = WinPtr->_maxx;
WinStat->LnArry[WinPtr->_cury].Touched = TRUE;
return OK;
}
wdelch(WinPtr)
WINDOW *WinPtr;
{
int i;
struct WindowState *WinStat;
if(!(WinStat = (struct WindowState *)WinPtr->_WinStat))
return ERR;
/* shuffle line along to the left */
for (i = WinPtr->_curx; i < WinPtr->_maxx; i++)
WinStat->LnArry[WinPtr->_cury].Line[i] = WinStat->LnArry[WinPtr->_cury].Line[i+1];
WinStat->LnArry[WinPtr->_cury].Line[i] = ' '; /* Blank last char */
WinStat->LnArry[WinPtr->_cury].StartCol = min(WinStat->LnArry[WinPtr->_cury].StartCol, WinPtr->_curx);
WinStat->LnArry[WinPtr->_cury].EndCol = WinPtr->_maxx;
WinStat->LnArry[WinPtr->_cury].Touched = TRUE;
return OK;
}
wclear(WinPtr)
WINDOW *WinPtr;
{
int Line, Col;
struct WindowState *WinStat;
if(!(CursesFlags & CFLAG_INITSCR)) /* Haven't called initscr() */
return ERR;
if(!(WinStat = (struct WindowState *)WinPtr->_WinStat))
return ERR;
for(Line=0; Line<WinStat->NLines; Line++) {
memset(WinStat->LnArry[Line].Line, ' ', WinPtr->_maxx + 1);
memset(WinStat->LnArry[Line].LRLine, ' ', WinPtr->_maxx + 1);
for(Col = 0; Col <= WinPtr->_maxx; Col++) {
WinStat->LnArry[Line].ATTRS[Col] = WinPtr->_attrs;
WinStat->LnArry[Line].LRATTRS[Col] = WinPtr->_attrs;
}
WinStat->LnArry[Line].Touched = FALSE;
WinStat->LnArry[Line].StartCol = WinPtr->_maxx;
WinStat->LnArry[Line].EndCol = 0;
}
WinPtr->_curx = 0;
WinPtr->_cury = 0;
WinPtr->_cls = TRUE;
return OK;
}
werase(WinPtr)
WINDOW *WinPtr;
{
int Line, Col;
struct WindowState *WinStat;
if(!(CursesFlags & CFLAG_INITSCR)) /* Haven't called initscr() */
return ERR;
if(!(WinStat = (struct WindowState *)WinPtr->_WinStat))
return ERR;
/* Blank screen image */
for(Line=0; Line<WinStat->NLines; Line++) {
memset(WinStat->LnArry[Line].Line, ' ', WinPtr->_maxx + 1);
for(Col = 0; Col <= WinPtr->_maxx; Col++)
WinStat->LnArry[Line].ATTRS[Col] = WinPtr->_attrs;
WinStat->LnArry[Line].Touched = TRUE;
WinStat->LnArry[Line].StartCol = 0;
WinStat->LnArry[Line].EndCol = WinPtr->_maxx;
}
WinPtr->_curx = 0;
WinPtr->_cury = 0;
return OK;
}
clearok(WinPtr, flag)
WINDOW *WinPtr;
int flag;
{
if(!(CursesFlags & CFLAG_INITSCR)) /* Haven't called initscr() */
return ERR;
WinPtr->_clear = (flag) ? TRUE : FALSE;
return OK;
}
wclrtoeol(WinPtr)
WINDOW *WinPtr;
{
short x, y;
int len;
char Buffer[100];
if(!(CursesFlags & CFLAG_INITSCR)) /* Haven't called initscr() */
return ERR;
x = WinPtr->_curx;
y = WinPtr->_cury;
len = WinPtr->_maxx - WinPtr->_curx + 1;
memset(Buffer, ' ', len);
Buffer[len] = '\0';
waddstr(WinPtr, Buffer);
wmove(WinPtr, y, x);
return OK;
}
wclrtobot(WinPtr)
WINDOW *WinPtr;
{
short x, y;
int i;
if(!(CursesFlags & CFLAG_INITSCR)) /* Haven't called initscr() */
return ERR;
x = WinPtr->_curx;
y = WinPtr->_cury;
wclrtoeol(WinPtr);
for(i = WinPtr->_cury + 1; i <= WinPtr->_maxy; i++) {
wmove(WinPtr, i, 0);
wclrtoeol(WinPtr);
}
wmove(WinPtr, y, x);
return OK;
}
static int GetNextChar(WinPtr)
WINDOW *WinPtr;
{
static unsigned char buffer[RAWBUFSIZ], BufPos = 0, NumChars = 0;
int Class, i;
struct IntuiMessage *Message;
static struct InputEvent ievent = { NULL, IECLASS_RAWKEY, 0, 0, 0 };
if(BufPos < NumChars) /* If we still hav some chars then return next */
return (int)buffer[BufPos++];
while (BufPos == NumChars) {
/* Get message if there is one allready queued */
Message = (struct IntuiMessage *)GetMsg(CursesWindow->UserPort);
if(!Message) {
/* Nuffin yet */
if(WinPtr->_nodelay) /* If non-blocking return ERR */
return ERR;
else { /* Wait for character */
Wait(1<<CursesWindow->UserPort->mp_SigBit);
Message = (struct IntuiMessage *)GetMsg(CursesWindow->UserPort);
}
}
if(!Message) /* Try again */
continue;
Class = Message->Class;
switch(Class) {
case RAWKEY:
BufPos = 0;
ievent.ie_Code = Message->Code;
ievent.ie_Qualifier = Message->Qualifier;
ievent.ie_position.ie_addr = *((APTR*)Message->IAddress);
NumChars = RawKeyConvert(&ievent, buffer, RAWBUFSIZ, 0L);
ReplyMsg((struct Message *)Message);
if(!NumChars) /* If no characters then try again */
break;
if(CursesFlags & CFLAG_ECHO)
for(i=0; i<NumChars; i++)
DoEcho(WinPtr, buffer[i]);
/* Translate id keypad set to TRUE */
if(WinPtr->_use_keypad) {
switch(NumChars) {
case 1:
NumChars = 0; /* Translation will use up all chars */
return (int)buffer[0];
case 2: /* ARROW KEY */
NumChars = 0; /* Translation will use up all chars */
if(buffer[0] != 155)
return -1;
switch(buffer[1]) {
case 65: return KEY_UP;
case 66: return KEY_DOWN;
case 67: return KEY_RIGHT;
case 68: return KEY_LEFT;
default: return -1;
}
case 3: /* FUNCTION KEY */
NumChars = 0; /* Translation will use up all chars */
if(buffer[0] != 155)
return -1;
if(buffer[2] != 126)
return -1;
if(buffer[1] == 63)
return KEY_HELP;
return KEY_F0 + (buffer[1] - 48); /* KEY_F0 = F1 */
default:
NumChars = 0; /* Translation will use up all chars */
return -1;
}
}
break;
default:
ReplyMsg((struct Message *)Message);
break;
}
}
return (int)buffer[BufPos++];
}
flushinp()
{
GetchRPos = 0;
GetchWPos = 0;
return OK;
}
wgetch(WinPtr)
WINDOW *WinPtr;
{
static int buffer[256]; /* Cyclic buffer */
static unsigned char forward = FALSE;
int Ret;
if(!(CursesFlags & CFLAG_INITSCR)) /* Haven't called initscr() */
return ERR;
while(GetchRPos == GetchWPos || (!(CursesFlags & CFLAG_CBREAK) && !forward)) {
if(WinPtr->_nodelay)
return GetNextChar(WinPtr);
if((Ret = GetNextChar(WinPtr)) >= 0)
buffer[GetchWPos++] = Ret;
if(Ret == (int)'\r')
forward = TRUE;
}
if(buffer[GetchRPos] == '\r') {
buffer[GetchRPos] = '\n';
forward = FALSE;
}
return((int)buffer[GetchRPos++]);
}
wgetstr(WinPtr, ptr)
WINDOW *WinPtr;
char *ptr;
{
char done = FALSE, *BuffStart;
unsigned char TempFlag; /* Used to restore flags after */
if(!(CursesFlags & CFLAG_INITSCR)) /* Haven't called initscr() */
return ERR;
BuffStart = ptr;
/* Will need to be in CBREAK mode for this */
TempFlag = CursesFlags;
CursesFlags |= CFLAG_CBREAK;
while(!done) {
switch(*ptr = wgetch(WinPtr)) {
case -1: /* wgetch() returned ERROR */
*ptr = '\0';
CursesFlags = TempFlag;
return -1;
case '\n':
case '\r':
*ptr = '\0';
done = TRUE;
break;
case '\b':
if(--ptr < BuffStart) /* Don't move before start */
ptr = BuffStart;
else if(CursesFlags & CFLAG_ECHO) {
/* Do BS SP BS processing */
mvcur(CursorLine, CursorCol, CursorLine, CursorCol - 1); /* BS */
DoEcho(WinPtr, ' '); /* SP */
mvcur(CursorLine, CursorCol, CursorLine, CursorCol - 1); /* BS */
}
break;
default:
ptr++;
break;
}
}
CursesFlags = TempFlag;
return 0;
}
winch(WinPtr)
WINDOW *WinPtr;
{
struct WindowState *WinStat;
if(!(CursesFlags & CFLAG_INITSCR)) /* Haven't called initscr() */
return ERR;
if(!(WinStat = (struct WindowState *)WinPtr->_WinStat))
return ERR;
return (int)WinStat->LnArry[WinPtr->_cury].Line[WinPtr->_curx];
}
static void DoEcho(WinPtr, c)
WINDOW *WinPtr;
char c;
{
short x, y;
struct WindowState *WinStat;
if(!(WinStat = (struct WindowState *)WinPtr->_WinStat))
return;
if(c == BS || c == CR) /* Don't echo Backspace or Return */
return;
x = CursorCol * 8;
y = 6 + CursorLine * 8;
ZapCursor();
SetDrMd(RPort, JAM2);
SetAPen(RPort, WinPtr->_attrs & 0x0f);
Move(RPort, x, y);
Text(RPort, &c, 1);
DrawCursor();
/* Update curscr */
if(WinPtr != curscr) {
wmove(curscr, CursorLine, CursorCol);
waddch(curscr, c);
}
/* Update Line structure */
WinStat->LnArry[CursorLine-WinPtr->_begy].Line[CursorCol-WinPtr->_begx] = c;
WinStat->LnArry[CursorLine-WinPtr->_begy].LRLine[CursorCol-WinPtr->_begx] = c;
WinStat->LnArry[CursorLine-WinPtr->_begy].ATTRS[CursorCol-WinPtr->_begx] = WinPtr->_attrs;
WinStat->LnArry[CursorLine-WinPtr->_begy].LRATTRS[CursorCol-WinPtr->_begx] = WinPtr->_attrs;
/* Move current position one to the right */
if(++WinPtr->_curx > WinPtr->_maxx)
WinPtr->_curx = WinPtr->_maxx;
mvcur(CursorLine, CursorCol, CursorLine, CursorCol + 1);
}
wmove(WinPtr, Line, Col)
WINDOW *WinPtr;
short Line, Col;
{
if(!(CursesFlags & CFLAG_INITSCR)) /* Haven't called initscr() */
return ERR;
if(Line<0 || Line>WinPtr->_maxy)
return ERR;
if(Col<0 || Col>WinPtr->_maxx)
return ERR;
WinPtr -> _cury = Line;
WinPtr -> _curx = Col;
WinPtr -> _flags |= CWF_MOVED;
return OK;
}
mvcur(CurLine, CurCol, NewLine, NewCol)
int CurLine, CurCol, NewLine, NewCol;
{
/* Could check CurLine and CurCol but this would make it fail too often */
ZapCursor();
CursorLine = NewLine;
CursorCol = NewCol;
DrawCursor();
return OK;
}
printw(fmt, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9)
char *fmt;
double A0, A1, A2, A3, A4, A5, A6, A7, A8, A9;
{
int Ret;
char buffer[BUFSIZ];
Ret = sprintf(buffer, fmt, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9);
waddstr(stdscr, buffer);
return Ret;
}
wprintw(WinPtr, fmt, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9)
WINDOW *WinPtr;
char *fmt;
double A0, A1, A2, A3, A4, A5, A6, A7, A8, A9;
{
int Ret;
char buffer[BUFSIZ];
Ret = sprintf(buffer, fmt, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9);
waddstr(WinPtr, buffer);
return Ret;
}
mvprintw(Line, Col, fmt, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9)
short Line, Col;
char *fmt;
double A0, A1, A2, A3, A4, A5, A6, A7, A8, A9;
{
int Ret;
char buffer[BUFSIZ];
Ret = sprintf(buffer, fmt, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9);
wmove(stdscr, Line, Col);
waddstr(stdscr, buffer);
return Ret;
}
mvwprintw(WinPtr, Line, Col, fmt, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9)
WINDOW *WinPtr;
short Line, Col;
char *fmt;
double A0, A1, A2, A3, A4, A5, A6, A7, A8, A9;
{
int Ret;
char buffer[BUFSIZ];
Ret = sprintf(buffer, fmt, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9);
wmove(WinPtr, Line, Col);
waddstr(WinPtr, buffer);
return Ret;
}
wrefresh(WinPtr)
WINDOW *WinPtr;
{
int i, j;
unsigned long style;
short Line;
struct WindowState *WinStat;
char Buffer[BUFSIZ];
void Optimise();
if(WinPtr == curscr)
touchwin(WinPtr);
if(!(WinStat = (struct WindowState *)WinPtr->_WinStat))
return ERR;
ZapCursor();
/*
* It is possible for no printing since last refresh, but for
* a move to have been done...
*/
if(WinPtr->_flags & CWF_MOVED) {
WinPtr->_flags &= ~CWF_MOVED;
CursorLine = WinPtr->_cury + WinPtr->_begy;
CursorCol = WinPtr->_curx + WinPtr->_begx;
}
/*
* If clearok has been called, then clear on every refresh.
*/
if(WinPtr->_clear || WinPtr->_cls) {
WinPtr->_cls = FALSE;
SetAPen(RPort, 0);
SetDrMd(RPort, JAM2);
RectFill(RPort, (WinPtr->_begx * 8), (WinPtr->_begy * 8),
((WinPtr->_begx + WinPtr->_maxx) * 8) + 7,
((WinPtr->_begy + WinPtr->_maxy) * 8 + 7));
}
if(CursesFlags & CFLAG_CURSOR) {
CursorLine = WinPtr->_cury + WinPtr->_begy;
CursorCol = WinPtr->_curx + WinPtr->_begx;
}
for(Line=0; Line<WinStat->NLines; Line++) {
/* if clearok set then must refresh everything */
if(WinPtr->_clear) {
memset(WinStat->LnArry[Line].LRLine, ' ', WinPtr->_maxx+1);
WinStat->LnArry[Line].Touched = TRUE;
WinStat->LnArry[Line].StartCol = 0;
WinStat->LnArry[Line].EndCol = WinPtr->_maxx;
}
Optimise(&WinStat->LnArry[Line]);
if(WinStat->LnArry[Line].Touched) {
j = WinStat->LnArry[Line].StartCol;
for(i=WinStat->LnArry[Line].StartCol + 1; i<=WinStat->LnArry[Line].EndCol; i++) {
if(WinStat->LnArry[Line].ATTRS[i] != WinStat->LnArry[Line].ATTRS[j]) {
/* Print what we've got */
SetAPen(RPort, WinStat->LnArry[Line].ATTRS[j] & 017);
if(WinStat->LnArry[Line].ATTRS[j] & (A_REVERSE | A_STANDOUT))
SetDrMd(RPort, JAM2|INVERSVID);
else
SetDrMd(RPort, JAM2);
style = FS_NORMAL;
if(WinStat->LnArry[Line].ATTRS[j] & A_BOLD)
style |= FSF_BOLD;
if(WinStat->LnArry[Line].ATTRS[j] & A_UNDERLINE)
style |= FSF_UNDERLINED;
SetSoftStyle(RPort, style, ~0L);
Move(RPort, (j+WinPtr->_begx) * 8, 6 + (Line+WinPtr->_begy) * 8);
Text(RPort, &WinStat->LnArry[Line].Line[j], i-j);
/*
* Update the record of the current screen state.
*/
if(WinPtr != curscr) {
wmove(curscr, Line+WinPtr->_begy, j+WinPtr->_begx);
memcpy(Buffer, &WinStat->LnArry[Line].Line[j], i-j);
Buffer[i-j] = '\0';
waddstr(curscr, Buffer);
}
j = i;
}
}
if(j < i) {
SetAPen(RPort, WinStat->LnArry[Line].ATTRS[j] & 017);
if(WinStat->LnArry[Line].ATTRS[j] & (A_STANDOUT | A_REVERSE))
SetDrMd(RPort, JAM2|INVERSVID);
else
SetDrMd(RPort, JAM2);
style = FS_NORMAL;
if(WinStat->LnArry[Line].ATTRS[j] & A_BOLD)
style |= FSF_BOLD;
if(WinStat->LnArry[Line].ATTRS[j] & A_UNDERLINE)
style |= FSF_UNDERLINED;
SetSoftStyle(RPort, style, ~0L);
Move(RPort, (j+WinPtr->_begx) * 8, 6 + (Line+WinPtr->_begy) * 8);
Text(RPort, &(WinStat->LnArry[Line].Line[j]), i-j);
/*
* Update the record of the current screen state.
*/
if(WinPtr != curscr) {
wmove(curscr, Line+WinPtr->_begy, j+WinPtr->_begx);
memcpy(Buffer, &WinStat->LnArry[Line].Line[j], i-j);
Buffer[i-j] = '\0';
waddstr(curscr, Buffer);
}
}
WinStat->LnArry[Line].Touched = FALSE;
WinStat->LnArry[Line].StartCol = WinPtr->_maxx;
WinStat->LnArry[Line].EndCol = 0;
}
/*
* Copy line and attrs to LR for Optimise code
*/
memcpy(WinStat->LnArry[Line].LRLine, WinStat->LnArry[Line].Line, WinPtr->_maxx+1);
memcpy(WinStat->LnArry[Line].LRATTRS, WinStat->LnArry[Line].ATTRS, sizeof(short) * (WinPtr->_maxx+1));
}
DrawCursor();
return OK;
}
static void ToggleCursor(Line, Col)
{
SetDrMd(RPort, JAM2 | INVERSVID | COMPLEMENT);
Move(RPort, Col*8, 6 + Line*8);
Text(RPort, " ", 1);
}
static void
ZapCursor()
{
/* If there was a cursor then blank it */
if(LCursorCol >= 0 && LCursorLine >= 0)
ToggleCursor(LCursorLine, LCursorCol);
LCursorCol = LCursorLine = -1;
}
static void DrawCursor()
{
/* Draw cursor */
if(CursesFlags & CFLAG_CURSOR)
ToggleCursor(CursorLine, CursorCol);
if(CursesFlags & CFLAG_CURSOR) {
LCursorCol = CursorCol;
LCursorLine = CursorLine;
} else {
LCursorCol = -1;
LCursorLine = -1;
}
}
scanw(fmt, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9)
char *fmt;
long A0, A1, A2, A3, A4, A5, A6, A7, A8, A9;
{
char buffer[BUFSIZ];
wgetstr(stdscr, buffer);
return sscanf(buffer, fmt, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9);
}
wscanw(WinPtr, fmt, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9)
WINDOW *WinPtr;
char *fmt;
long A0, A1, A2, A3, A4, A5, A6, A7, A8, A9;
{
char buffer[BUFSIZ];
wgetstr(WinPtr, buffer);
return sscanf(buffer, fmt, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9);
}
mvscanw(Line, Col, fmt, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9)
short Line, Col;
char *fmt;
long A0, A1, A2, A3, A4, A5, A6, A7, A8, A9;
{
char buffer[BUFSIZ];
wmove(stdscr, Line, Col);
wgetstr(stdscr, buffer);
return sscanf(buffer, fmt, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9);
}
mvwscanw(WinPtr, Line, Col, fmt, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9)
WINDOW *WinPtr;
short Line, Col;
char *fmt;
long A0, A1, A2, A3, A4, A5, A6, A7, A8, A9;
{
char buffer[BUFSIZ];
wmove(WinPtr, Line, Col);
wgetstr(WinPtr, buffer);
return sscanf(buffer, fmt, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9);
}
wstandout(WinPtr)
WINDOW *WinPtr;
{
if(!(CursesFlags & CFLAG_INITSCR)) /* Haven't called initscr() */
return ERR;
WinPtr->_attrs |= A_STANDOUT;
}
wstandend(WinPtr)
WINDOW *WinPtr;
{
if(!(CursesFlags & CFLAG_INITSCR)) /* Haven't called initscr() */
return ERR;
WinPtr->_attrs &= ~A_STANDOUT;
}
wattrset(WinPtr, attr)
WINDOW *WinPtr;
short attr;
{
if(!(CursesFlags & CFLAG_INITSCR)) /* Haven't called initscr() */
return ERR;
/*
* Older code may inadvertently reset the attributes and set the
* forground colour to 0, in this case, set it to white.
*/
if(!(attr & 017))
attr |= COLOR_WHITE;
WinPtr->_attrs = attr;
return OK;
}
wattron(WinPtr, attr)
WINDOW *WinPtr;
short attr;
{
if(!(CursesFlags & CFLAG_INITSCR)) /* Haven't called initscr() */
return ERR;
/* If attributes contain a colour change then mask off old colour */
if(attr & 017)
WinPtr->_attrs &= ~017;
WinPtr->_attrs |= attr;
return OK;
}
wattroff(WinPtr, attr)
WINDOW *WinPtr;
short attr;
{
if(!(CursesFlags & CFLAG_INITSCR)) /* Haven't called initscr() */
return ERR;
WinPtr->_attrs &= ~attr;
return OK;
}
cbreak()
{
if(!(CursesFlags & CFLAG_INITSCR)) /* Haven't called initscr() */
return ERR;
CursesFlags |= CFLAG_CBREAK;
return OK;
}
nocbreak()
{
if(!(CursesFlags & CFLAG_INITSCR)) /* Haven't called initscr() */
return ERR;
CursesFlags &= ~CFLAG_CBREAK;
return OK;
}
raw()
{
if(!(CursesFlags & CFLAG_INITSCR)) /* Haven't called initscr() */
return ERR;
CursesFlags |= CFLAG_CBREAK;
return OK;
}
noraw()
{
if(!(CursesFlags & CFLAG_INITSCR)) /* Haven't called initscr() */
return ERR;
CursesFlags &= ~CFLAG_CBREAK;
return OK;
}
idlok(WinPtr, flag)
WINDOW *WinPtr;
int flag;
{
/* This function is to enable hardware insert/delete line */
return OK;
}
winsertln(WinPtr)
WINDOW *WinPtr;
{
Scroll(WinPtr, WinPtr->_cury, WinPtr->_maxy, SCROLL_DOWN);
return OK;
}
wdeleteln(WinPtr)
WINDOW *WinPtr;
{
Scroll(WinPtr, WinPtr->_cury, WinPtr->_maxy, SCROLL_UP);
return OK;
}
nodelay(WinPtr, flag)
WINDOW *WinPtr;
int flag;
{
if(!(CursesFlags & CFLAG_INITSCR)) /* Haven't called initscr() */
return ERR;
WinPtr->_nodelay = flag;
return OK;
}
echo()
{
if(!(CursesFlags & CFLAG_INITSCR)) /* Haven't called initscr() */
return ERR;
CursesFlags |= CFLAG_ECHO;
return OK;
}
noecho()
{
if(!(CursesFlags & CFLAG_INITSCR)) /* Haven't called initscr() */
return ERR;
CursesFlags &= ~CFLAG_ECHO;
return OK;
}
keypad(WinPtr, flag)
WINDOW *WinPtr;
char flag;
{
if(!(CursesFlags & CFLAG_INITSCR)) /* Haven't called initscr() */
return ERR;
WinPtr->_use_keypad = flag?TRUE:FALSE;
return OK;
}
beep()
{
if(!(CursesFlags & CFLAG_INITSCR)) /* Haven't called initscr() */
return ERR;
AIOptr = (struct IOAudio *) AllocMem(sizeof(struct IOAudio), MEMF_CHIP|MEMF_PUBLIC);
if(!AIOptr)
exit(1);
port = (struct MsgPort *)CreatePort(0, 0);
if(!port) {
FreeMem(AIOptr, sizeof(struct IOAudio));
return ERR;
}
AIOptr->ioa_Request.io_Message.mn_ReplyPort = port;
AIOptr->ioa_Request.io_Message.mn_Node.ln_Pri = 0;
AIOptr->ioa_Request.io_Command = ADCMD_ALLOCATE;
AIOptr->ioa_Request.io_Flags = ADIOF_NOWAIT;
AIOptr->ioa_AllocKey = 0;
AIOptr->ioa_Data = whichannel;
AIOptr->ioa_Length = sizeof(whichannel);
device = OpenDevice("audio.device", 0L, (struct IORequest *)AIOptr, 0L);
if(device) {
printf("Curses beep() - Can't open Audio Device\n");
FreeMem(AIOptr, sizeof(struct IOAudio));
return ERR;
}
sound_data = (UBYTE *) AllocMem(SOUNDLENGTH, MEMF_CHIP|MEMF_PUBLIC);
if(!sound_data) {
FreeMem(AIOptr, sizeof(struct IOAudio));
return ERR;
}
sound_data[0]=127;
sound_data[1]=-127;
AIOptr->ioa_Request.io_Message.mn_ReplyPort = port;
AIOptr->ioa_Request.io_Command = CMD_WRITE;
AIOptr->ioa_Request.io_Flags = ADIOF_PERVOL;
AIOptr->ioa_Data = sound_data;
AIOptr->ioa_Cycles = 200;
AIOptr->ioa_Length = SOUNDLENGTH;
AIOptr->ioa_Period = 2000;
AIOptr->ioa_Volume = 64;
BeginIO((struct IORequest *)AIOptr);
WaitIO((struct IORequest *)AIOptr);
FreeMem(sound_data, SOUNDLENGTH);
DeletePort(port);
CloseDevice((struct IORequest *)AIOptr);
FreeMem(AIOptr, sizeof(struct IOAudio));
}
flash()
{
if(!(CursesFlags & CFLAG_INITSCR)) /* Haven't called initscr() */
return ERR;
DisplayBeep(CursesScreen);
}
leaveok(WinPtr, flag)
WINDOW *WinPtr;
int flag;
{
if(!(CursesFlags & CFLAG_INITSCR)) /* Haven't called initscr() */
return ERR;
if(flag) {
CursorCol = CursorLine = -1;
CursesFlags &= ~CFLAG_CURSOR;
} else {
CursesFlags |= CFLAG_CURSOR;
}
return OK;
}
resetty()
{
return OK;
}
savetty()
{
return OK;
}
resetterm()
{
return OK;
}
fixterm()
{
return OK;
}
saveterm()
{
return OK;
}
baudrate()
{
return 9600;
}
nl()
{
CursesFlags |= CFLAG_NLCR;
return OK;
}
nonl()
{
CursesFlags &= ~CFLAG_NLCR;
return OK;
}
crmode()
{
return (cbreak());
}
nocrmode()
{
return (nocbreak());
}
box(WinPtr, vert, hor)
WINDOW *WinPtr;
char vert, hor;
{
int i;
short CurY, CurX;
CurY = WinPtr->_cury;
CurX = WinPtr->_curx;
if(vert < 32 || vert > 126)
vert = '|';
if(hor < 32 || hor > 126)
hor = '-';
for(i=0; i<=WinPtr->_maxx; i++) {
mvwaddch(WinPtr, 0, i, hor); /* Top horizontal */
mvwaddch(WinPtr, WinPtr->_maxy, i, hor); /* Bottom horizontal */
}
for(i=1; i<WinPtr->_maxy; i++) {
mvwaddch(WinPtr, i, 0, vert); /* Left vertical */
mvwaddch(WinPtr, i, WinPtr->_maxx, vert); /* Right vertical */
}
WinPtr -> _cury = CurY;
WinPtr -> _curx = CurX;
return OK;
}
WINDOW *subwin(Orig, NLines, NCols, StartLine, StartCol)
WINDOW *Orig;
unsigned int NLines, NCols, StartLine, StartCol;
{
WINDOW *WinPtr, *CreatWindow();
if(!(WinPtr = CreatWindow(NLines, NCols, StartLine, StartCol, Orig))) {
printf("WARNING - subwin() failed, returning stdscr !!\n");
return stdscr; /* Failed */
}
return WinPtr;
}
WINDOW *newwin(NLines, NCols, StartLine, StartCol)
unsigned int NLines, NCols, StartLine, StartCol;
{
WINDOW *WinPtr, *CreatWindow();
if(!(WinPtr = CreatWindow(NLines, NCols, StartLine, StartCol, NULL))) {
printf("WARNING - newwin() failed, returning stdscr !!\n");
return stdscr; /* Failed */
}
wclear(WinPtr);
return WinPtr;
}
/* Orig is NULL and StartCol/Line are not used for newwin() calls */
static WINDOW *CreatWindow(NLines, NCols, StartLine, StartCol, Orig)
int NLines, NCols, StartLine, StartCol;
WINDOW *Orig;
{
int Line, j;
struct WindowState *NewWinStat, *TmpWinPtr, *OrgWinStat = NULL;
char *malloc();
/* If either are zero then make them max */
if(!NLines)
NLines = LINES - StartLine;
if(!NCols)
NCols = COLS - StartCol;
if(NLines>LINES || NCols>COLS || StartLine>LINES || StartCol>COLS)
return (struct WINDOW *)NULL;
if(StartLine < 0)
StartLine = 0;
if(StartCol < 0)
StartCol = 0;
if(Orig)
OrgWinStat = (struct WindowState *)Orig->_WinStat;
/* Create a new WinStat structure */
if((NewWinStat=(struct WindowState *)malloc(sizeof(struct WindowState)))
== (struct WindowState *)NULL) {
fprintf(stderr, "CreatWindow() - Not enough memory\n");
return (struct WINDOW *)NULL;
}
NewWinStat->ParentWin = Orig;
NewWinStat->Next = (struct WindowState *)NULL;
NewWinStat->Prev = (struct WindowState *)NULL;
NewWinStat->ScrollTop = 0;
NewWinStat->ScrollBot = NLines - 1;
NewWinStat->NLines = NLines;
/* Allocate space for LnArry[] */
if(!(NewWinStat->LnArry = (struct LineElement *)malloc(sizeof(struct LineElement)*LINES))) {
fprintf(stderr, "CreatWindow() - Not enough memory\n");
return (struct WINDOW *)NULL;
}
/* Allocate space for Line, LRLine e.t.c */
for(Line = 0; Line < NLines; Line++) {
if(OrgWinStat) { /* If this is a subwindow */
/* Set up pointers into parent window */
NewWinStat->LnArry[Line].Line =
&OrgWinStat->LnArry[Line+StartLine].Line[StartCol];
NewWinStat->LnArry[Line].LRLine =
&OrgWinStat->LnArry[Line+StartLine].LRLine[StartCol];
NewWinStat->LnArry[Line].ATTRS =
&OrgWinStat->LnArry[Line+StartLine].ATTRS[StartCol];
NewWinStat->LnArry[Line].LRATTRS =
&OrgWinStat->LnArry[Line+StartLine].LRATTRS[StartCol];
} else { /* New window, allocate space for lines */
/* malloc lines and ATTRS */
if((NewWinStat->LnArry[Line].Line = malloc(NCols)) == NULL) {
fprintf(stderr, "CreatWindow() - Not enough memory\n");
return (struct WINDOW *)NULL;
}
if((NewWinStat->LnArry[Line].LRLine = malloc(NCols)) == NULL) {
fprintf(stderr, "CreatWindow() - Not enough memory\n");
return (struct WINDOW *)NULL;
}
if((NewWinStat->LnArry[Line].ATTRS =
(short *)malloc(NCols*sizeof(short))) == NULL) {
fprintf(stderr, "CreatWindow() - Not enough memory\n");
return (struct WINDOW *)NULL;
}
if((NewWinStat->LnArry[Line].LRATTRS =
(short *)malloc(NCols*sizeof(short))) == NULL) {
fprintf(stderr, "CreatWindow() - Not enough memory\n");
return (struct WINDOW *)NULL;
}
/* The optimiser will untouch any lines not used */
memset(NewWinStat->LnArry[Line].LRLine, ' ', NCols);
for(j=0; j<NCols; j++)
NewWinStat->LnArry[Line].LRATTRS[j] = A_NORMAL | COLOR_WHITE;
}
NewWinStat->LnArry[Line].Touched = FALSE;
NewWinStat->LnArry[Line].StartCol = NCols;
NewWinStat->LnArry[Line].EndCol = 0;
}
/* Add to Window Stat list */
if(HeadWindowList) {
TmpWinPtr = HeadWindowList;
while(TmpWinPtr->Next)
TmpWinPtr = TmpWinPtr->Next;
TmpWinPtr->Next = NewWinStat;
NewWinStat->Prev = TmpWinPtr;
} else {
/* This is the first window i.e. stdscr */
HeadWindowList = NewWinStat;
}
/* Initialise state of the window structure */
NewWinStat->Window._cury = 0;
NewWinStat->Window._curx = 0;
NewWinStat->Window._maxy = NLines - 1;
NewWinStat->Window._maxx = NCols - 1;
NewWinStat->Window._begy = StartLine;
NewWinStat->Window._begx = StartCol;
NewWinStat->Window._flags = 0;
NewWinStat->Window._attrs = A_NORMAL | COLOR_WHITE;
NewWinStat->Window._clear = FALSE;
NewWinStat->Window._cls = TRUE;
NewWinStat->Window._scroll = FALSE;
NewWinStat->Window._use_keypad = 0;
NewWinStat->Window._use_meta = 0;
NewWinStat->Window._nodelay = 0;
NewWinStat->Window._WinStat = (char *)NewWinStat;
return &NewWinStat->Window;
}
touchwin(WinPtr)
WINDOW *WinPtr;
{
struct WindowState *WinStat;
int Line;
if(!(CursesFlags & CFLAG_INITSCR))
return ERR;
if(!(WinStat = (struct WindowState *)WinPtr->_WinStat))
return ERR;
for(Line=0; Line<WinStat->NLines; Line++) {
WinStat->LnArry[Line].Touched = TRUE;
/* Mark whole line as refreshable */
WinStat->LnArry[Line].StartCol = 0;
WinStat->LnArry[Line].EndCol = WinPtr->_maxx;
/* Dump optimisation */
memset(WinStat->LnArry[Line].LRLine, 0, WinPtr->_maxx+1);
}
return OK;
}
delwin(WinPtr)
WINDOW *WinPtr;
{
struct WindowState *WinStat;
int LineNo;
if(!(CursesFlags & CFLAG_INITSCR))
return ERR;
if(!(WinStat = (struct WindowState *)WinPtr->_WinStat))
return ERR;
if(!WinStat->ParentWin) {
/* If it's a real window, free up Line, LRLine, ATTRS, LRATTRS */
for(LineNo=0; LineNo<WinStat->NLines; LineNo++) {
free(WinStat->LnArry[LineNo].Line);
free(WinStat->LnArry[LineNo].LRLine);
free(WinStat->LnArry[LineNo].ATTRS);
free(WinStat->LnArry[LineNo].LRATTRS);
}
}
/* Free up LnArry[] */
free(WinStat->LnArry);
/* Remove the winstat from the list */
if(WinStat == HeadWindowList) { /* if this is first window (stdscr) */
HeadWindowList = WinStat->Next;
if(HeadWindowList)
HeadWindowList->Prev = (struct WindowState *)NULL;
} else {
if(WinStat->Next)
WinStat->Next->Prev = WinStat->Prev;
if(WinStat->Prev)
WinStat->Prev->Next = WinStat->Next;
}
/* Free the winstat */
free(WinStat);
return OK;
}
mvwin(WinPtr, NewLine, NewCol)
WINDOW *WinPtr;
short NewLine, NewCol;
{
if(!(CursesFlags & CFLAG_INITSCR))
return ERR;
WinPtr->_begx = NewCol;
WinPtr->_begy = NewLine;
if(touchwin(WinPtr) == ERR)
return ERR;
return OK;
}
scroll(WinPtr)
WINDOW *WinPtr;
{
struct WindowState *WinStat;
if(!(CursesFlags & CFLAG_INITSCR))
return ERR;
if(!(WinStat = (struct WindowState *)WinPtr->_WinStat))
return ERR;
Scroll(WinPtr, WinStat->ScrollTop, WinStat->ScrollBot, SCROLL_UP);
return OK;
}
static Scroll(WinPtr, Top, Bottom, Direction)
WINDOW *WinPtr;
int Top, Bottom, Direction;
{
int Step, SLine, DLine, Col;
char *TLine, *TLRLine;
short *TATTRS, *TLRATTRS;
struct WindowState *WinStat;
if(!(WinStat = (struct WindowState *)WinPtr->_WinStat))
return ERR;
/* Store pointers to line that will be lost */
if(Direction == SCROLL_UP) {
Step = +1;
DLine = Top;
SLine = Top + Step;
} else {
Step = -1;
DLine = Bottom;
SLine = Bottom + Step;
}
TLine = WinStat->LnArry[DLine].Line;
TLRLine = WinStat->LnArry[DLine].LRLine;
TATTRS = WinStat->LnArry[DLine].ATTRS;
TLRATTRS = WinStat->LnArry[DLine].LRATTRS;
/* Move the lines */
for(;;) {
if((Direction == SCROLL_UP) && (DLine >= Bottom))
break; /* Done */
if((Direction == SCROLL_DOWN) && (DLine <= Top))
break; /* Done */
WinStat->LnArry[DLine].Line = WinStat->LnArry[SLine].Line;
WinStat->LnArry[DLine].LRLine = WinStat->LnArry[SLine].LRLine;
WinStat->LnArry[DLine].ATTRS = WinStat->LnArry[SLine].ATTRS;
WinStat->LnArry[DLine].LRATTRS = WinStat->LnArry[SLine].LRATTRS;
for(Col=0; Col <= WinStat->Window._maxx; Col++) {
WinStat->LnArry[DLine].ATTRS[Col] = WinStat->Window._attrs;
WinStat->LnArry[DLine].LRATTRS[Col] = 0;
}
SLine += Step;
DLine += Step;
}
/* Blank the Temp line */
memset(TLine, ' ', WinStat->Window._maxx+1);
memset(TLRLine, 0, WinStat->Window._maxx+1);
for(Col=0; Col <= WinStat->Window._maxx; Col++) {
TATTRS[Col] = WinStat->Window._attrs;
TLRATTRS[Col] = 0;
}
/* move in temp line */
WinStat->LnArry[DLine].Line = TLine;
WinStat->LnArry[DLine].LRLine = TLRLine;
WinStat->LnArry[DLine].ATTRS = TATTRS;
WinStat->LnArry[DLine].LRATTRS = TLRATTRS;
return OK;
}
wsetscrreg(WinPtr, top, bottom)
WINDOW *WinPtr;
short top, bottom;
{
struct WindowState *WinStat;
if(!(WinStat = (struct WindowState *)WinPtr->_WinStat))
return ERR;
WinStat->ScrollTop = top;
WinStat->ScrollBot = bottom;
return OK;
}
scrollok(WinPtr, flag)
WINDOW *WinPtr;
int flag;
{
WinPtr->_scroll = (flag) ? TRUE : FALSE;
return OK;
}
/*
* Simple implementation of wnoutrefresh() and doupdate()
*
* Date: 8th Oct 1990
*
* Author: SJR
*
*/
wnoutrefresh(WinPtr)
WINDOW *WinPtr;
{
struct RefreshElement *NewRefEl;
if(!(NewRefEl = (struct RefreshElement *)
malloc(sizeof(struct RefreshElement))))
return ERR;
/* Fill the new element in */
NewRefEl->Next = (struct RefreshElement *)NULL;
NewRefEl->WinPtr = WinPtr;
/* Add to start of refresh list */
if(HeadRefreshList)
NewRefEl->Next = HeadRefreshList;
HeadRefreshList = NewRefEl;
}
doupdate()
{
struct RefreshElement *ElPtr;
void ZapRElList();
ElPtr = HeadRefreshList;
while(ElPtr) {
if(wrefresh(ElPtr->WinPtr) == ERR)
return ERR;
ElPtr = ElPtr->Next;
}
ZapRElList(HeadRefreshList);
HeadRefreshList = (struct RefreshElement *)NULL;
return OK;
}
static void ZapRElList(ElPtr)
struct RefreshElement *ElPtr;
{
if(!ElPtr)
return;
if(ElPtr->Next)
ZapRElList(ElPtr->Next); /* Recurse my boy */
free(ElPtr);
}
static void Optimise(LinePtr)
struct LineElement *LinePtr;
{
int i;
if(!LinePtr->Touched)
return;
for(i=LinePtr->StartCol; i<=LinePtr->EndCol; i++) {
if((LinePtr->Line[i] != LinePtr->LRLine[i]) ||
(LinePtr->ATTRS[i] != LinePtr->LRATTRS[i]))
break;
LinePtr->StartCol++;
}
for(i=LinePtr->EndCol; i>=LinePtr->StartCol; i--) {
if((LinePtr->Line[i] != LinePtr->LRLine[i]) ||
(LinePtr->ATTRS[i] != LinePtr->LRATTRS[i]))
break;
LinePtr->EndCol--;
}
if(LinePtr->StartCol > LinePtr->EndCol)
LinePtr->Touched = FALSE;
}