[comp.sources.amiga] v91i037: Curses 1.22 - terminal screen handling and optimization package, Part05/08

amiga-request@ab20.larc.nasa.gov (Amiga Sources/Binaries Moderator) (03/04/91)

Submitted-by: sie@fulcrum.bt.co.uk (Simon Raybould)
Posting-number: Volume 91, Issue 037
Archive-name: libraries/curses-1.22/part05

#!/bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 5 (of 8)."
# Contents:  src/curses.c
# Wrapped by tadguy@ab20 on Sun Mar  3 18:04:29 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'src/curses.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/curses.c'\"
else
echo shar: Extracting \"'src/curses.c'\" \(44718 characters\)
sed "s/^X//" >'src/curses.c' <<'END_OF_FILE'
X/*
X *
X * Module       : curses.c
X *
X * Description  : AMIGA CURSES package.
X *
X * Author       : Simon Raybould  (sie@fulcrum.bt.co.uk)
X *
X * Date  V1.00a : 16th February 1990
X *       V1.10  : 30th July 1990
X *       V1.20a :  4th October 1990
X *       V1.20  :  7th November 1990
X *       V1.21  :  2nd December 1990 minor fixes
X *       V1.22  :  7th January 1991 bug fixes
X *
X */
X
X
X#include <intuition/intuition.h>
X#include <intuition/intuitionbase.h>
X#include <intuition/screens.h>
X#include <exec/types.h>
X#include <exec/memory.h>
X#include <devices/audio.h>
X
X#include "acurses.h"
X
X
X/* Main background screen */
Xstatic struct NewScreen NewScreen = {
X  0,                        /* LeftEdge */
X  0,                        /* TopEdge */
X  0,                        /* Width */
X  0,                        /* Height */
X  4,                        /* No. Bitplanes */
X  0, 1,                     /* DetailPen, BlockPen */
X  HIRES,                    /* ViewModes */
X  CUSTOMSCREEN,             /* Screen type */
X  (struct TextAttr *)NULL,  /* default font */
X  "Curses screen",          /* Screen Title */
X  (struct Gadget *)NULL,    /* Gadget list */
X  (struct BitMap *)NULL     /* custom bitmap */
X};
X
X/* Main background window */
Xstatic struct NewWindow NewWindow = {
X  0,                      /* Left edge */
X  0,                      /* Top edge */
X  0,                      /* Width */
X  0,                      /* Height */
X  -1, -1,                 /* Pens */
X  RAWKEY,                 /* IDCMP flags */
X  ACTIVATE | BORDERLESS,  /* Window flags */
X  NULL,                   /* First gadget */
X  NULL,                   /* Image data */
X  NULL,                   /* Title */
X  NULL,                   /* Pointer to screen structure */
X  NULL,                   /* Super BitMap ? */
X  0,0,0,0,                /* MIN/MAX sizing */
X  CUSTOMSCREEN            /* Type of screen */
X};
X
X/*
X *  Make author appear when right mouse button is pressed.
X */
X
Xstatic struct Menu _CursesMenu = {
X  NULL, 0, 0, 0, 0, 0,
X  "  AMIGA CURSES by Simon J Raybould  (sie@fulcrum.bt.co.uk) V1.22  07.Jan.1991",
X  NULL, 0, 0, 0, 0
X};
X
X/*
X * Should initialise all of these to NULL to be certain that
X * CleanExit() will function correctly. Most compilers will do this
X * anyway, but better safe than GURUed.
X */
X
Xstruct IntuitionBase *IntuitionBase = NULL;
Xstruct GfxBase *GfxBase = NULL;
X
Xstruct ConsoleDevice *ConsoleDevice = NULL;
Xstatic struct IOStdReq ioreq;
Xstatic struct Screen *CursesScreen = NULL;
Xstatic struct Window *CursesWindow = NULL;
X
Xstatic struct RastPort *RPort;
Xstatic struct ViewPort *VPort;
X
Xstatic unsigned char CursesFlags;  /* Global flags */
Xstatic short CursorCol = 0,CursorLine = 0,LCursorLine = -1,LCursorCol = -1;
Xstatic struct WindowState *HeadWindowList = (struct WindowState *)NULL;
Xstatic struct RefreshElement *HeadRefreshList=(struct RefreshElement *)NULL;
Xstatic struct IOAudio *AIOptr;
Xstatic struct MsgPort *port;
Xstatic ULONG device;
Xstatic BYTE *sound_data;
Xstatic UBYTE whichannel[] = { 1, 2, 4, 8 };
X
X/*
X *  void internal functions
X */
X
Xstatic void CleanExit(), CleanUp(), DoEcho();
Xstatic void ZapCursor(), DrawCursor();
X     
X/* Define a blank mouse pointer */
Xstatic USHORT __chip MyMsPtr[] = { 0, 0, 0, 0 };
X     
X#define NCOLOURS  32
X     
Xstatic UWORD ColourTable[] = {
X  0x000, 0xfff, 0xff0, 0xf80, 0x00f, 0xf0f, 0x0ff, 0xfff, 
X  0x620, 0xe50, 0x9f1, 0xeb0, 0x55f, 0x92f, 0x0f8, 0xccc, 
X  0x000, 0xd22, 0x000, 0xabc, 0x444, 0x555, 0x666, 0x777, 
X  0x888, 0x999, 0xaaa, 0xbbb, 0xccc, 0xddd, 0xeee, 0xfff
X};
X
XWINDOW *stdscr = (WINDOW *)NULL, *curscr = (WINDOW *)NULL;
Xint LINES=24, COLS=80;  /* Defaults */
X
X/*
X *  Need to be global so that flushinp() can reset them !
X */
Xstatic unsigned char GetchRPos = 0, GetchWPos = 0;
X
X/*
X *  Start of code.
X */
X
Xinitscr()
X{
X  ULONG IBaseLock;
X  char *Ptr, *getenv();
X  int Tmp;
X  
X  /*
X   *  It would be devestating if someone called initscr() twice
X   *  so make the second call fail.
X   */
X  if(CursesFlags & CFLAG_INITSCR)
X    return ERR;
X  
X  CursesFlags |= CFLAG_INITSCR;  /* Mark that we have called initscr() */
X  
X  if((IntuitionBase = (struct IntuitionBase *)
X      OpenLibrary("intuition.library", 0)) == NULL) {
X    fprintf(stderr, "Failed to open Intuition library");
X    CleanExit(10);
X  }
X  IBaseLock = LockIBase(0L);
X  NewScreen.Height = NewWindow.Height = IntuitionBase->ActiveScreen->Height;
X  NewScreen.Width = NewWindow.Width = IntuitionBase->ActiveScreen->Width;
X  UnlockIBase(IBaseLock);
X  /* Set interlace if height >= 400 */
X  if(NewScreen.Height>=400)
X    NewScreen.ViewModes |= LACE;
X  LINES = NewScreen.Height/8;
X  COLS = NewScreen.Width/8;
X  /* if LINES and/or COLS set as environment variables then use them */
X  if((Ptr = getenv("LINES"))) {
X    Tmp = atoi(Ptr);
X    if(Tmp>0 && Tmp<=LINES)
X      LINES = Tmp;
X  }
X  if((Ptr = getenv("COLS"))) {
X    Tmp = atoi(Ptr);
X    if(Tmp>0 && Tmp<=COLS)
X      COLS = Tmp;
X  }
X  /* Open graphics library */
X  if((GfxBase = (struct GfxBase *)
X      OpenLibrary("graphics.library", 0))==NULL) {
X    fprintf(stderr, "Failed to open Graphics library");
X    CleanExit(10);
X  }
X  /*
X   * must have the console.device opened to use RawKeyConvert()
X   */
X  
X  if(OpenDevice("console.device",-1L,(struct IORequest *)&ioreq,0L))
X    CleanExit(10);
X  ConsoleDevice=(struct ConsoleDevice *)ioreq.io_Device;
X  
X  if((CursesScreen=(struct Screen *)OpenScreen(&NewScreen)) == NULL) {
X    fprintf(stderr, "Failed to open Screen");
X    CleanExit(10);
X  }
X  RPort = &(CursesScreen->RastPort);
X  VPort = &(CursesScreen->ViewPort);
X  LoadRGB4(VPort, ColourTable, NCOLOURS);
X  SetDrMd(RPort, JAM2);
X  SetAPen(RPort, 1);
X  NewWindow.Screen = CursesScreen;  /* Must do this !! */
X  if((CursesWindow=(struct Window *)OpenWindow(&NewWindow)) == NULL) {
X    fprintf(stderr, "Failed to open Window\n");
X    CleanExit(10);
X  }
X  SetMenuStrip(CursesWindow, &_CursesMenu);
X  SetPointer(CursesWindow, MyMsPtr, 0, 0, 0, 0);  /*Remove mouse pointer*/
X  /* Create stdscr and curscr */
X  stdscr = newwin(LINES, COLS, 0, 0);
X  curscr = newwin(LINES, COLS, 0, 0);  /* used for redraws */
X  clearok(curscr, TRUE);  /* Clear curscr on every refresh */
X  
X  CursesFlags = CFLAG_ECHO | CFLAG_NLCR | CFLAG_CURSOR | CFLAG_INITSCR;
X  return OK;
X}
X
X/*
X *  Close the screen and libraries.
X */
X
Xendwin()                  /* called from main prior to exit. */
X{
X  void ZapWindows();
X  
X  if(!(CursesFlags & CFLAG_INITSCR)) {  /* haven't called initscr() */
X    return ERR;
X  }
X  ZapWindows(HeadWindowList);
X  CleanUp();
X  CursesFlags &= ~CFLAG_INITSCR;  /* Mark that we have called endwin() */
X  return OK;
X}
X
X/* Recursive routine to zap all windows and release data structures */
Xstatic void ZapWindows(WinStat)
X     struct WindowState *WinStat;
X{
X  if(!WinStat)
X    return;
X  if(WinStat->Next)
X    ZapWindows(WinStat->Next);  /* Recurse */
X  delwin(&WinStat->Window);
X}
X
Xstatic void CleanExit(RetCode)
X     int RetCode;
X{
X  CleanUp();
X  exit(RetCode);
X}
X
Xstatic void CleanUp()
X{
X  if(CursesWindow)
X    CloseWindow(CursesWindow);
X  if(CursesScreen)
X    CloseScreen(CursesScreen);
X  if(GfxBase)
X    CloseLibrary((struct Library *)GfxBase);
X  if(IntuitionBase)
X    CloseLibrary((struct Library *)IntuitionBase);
X}
X
Xinit_color(n, r, g, b)
X     short n;
X     unsigned char r, g, b;
X{
X  if(n<0 || n>15 || r>1000 || g>1000 || b>1000)
X    return ERR;
X  /* If 0 then leave, else subtract 1 */
X  if(r) r--;
X  if(g) g--;
X  if(g) g--;
X  
X  SetRGB4(VPort, n, r*16/1000, g*16/1000, b*16/1000);
X  return OK;
X}
X
Xstart_color()
X{
X  return OK;  /* No initialisation required to get colours going */
X}
X
Xhas_colors()
X{
X  return TRUE;  /* Yes baby we have colours on this bitch */
X}
X
X/*
X *  static because not implemented yet.
X */
Xstatic color_content(color, r, g, b)
X     short color, *r, *g, *b;
X{
X  return OK;
X}
X
Xwaddstr(WinPtr, Str)
X     WINDOW *WinPtr;
X     char *Str;
X{
X  struct WindowState *WinStat, *PWinStat = NULL;
X  short TmpAttrs;
X  
X  if(!*Str)
X    return OK;
X  if(!(WinStat = (struct WindowState *)WinPtr->_WinStat))
X    return ERR;
X  if(WinStat->ParentWin)
X    if(!(PWinStat = (struct WindowState *)WinStat->ParentWin->_WinStat))
X      return ERR;
X  
X  WinStat->LnArry[WinPtr->_cury].Touched = TRUE;
X  WinStat->LnArry[WinPtr->_cury].StartCol = min(WinStat->LnArry[WinPtr->_cury].StartCol, WinPtr->_curx);
X  if(PWinStat) {
X    PWinStat->LnArry[WinPtr->_cury + WinPtr->_begy].Touched = TRUE;
X    PWinStat->LnArry[WinPtr->_cury + WinPtr->_begy].StartCol = min(PWinStat->LnArry[WinPtr->_cury + WinPtr->_begy].StartCol, WinPtr->_curx + WinPtr->_begx);
X  }
X  while(*Str) {
X    switch(*Str) {
X    case '\t':
X      do {
X	WinStat->LnArry[WinPtr->_cury].Line[WinPtr->_curx] = ' ';
X	WinStat->LnArry[WinPtr->_cury].ATTRS[WinPtr->_curx++] = WinPtr->_attrs;
X      } while(WinPtr->_curx % 8);
X      break;
X    case '\n':
X      WinStat->LnArry[WinPtr->_cury].EndCol = max(WinStat->LnArry[WinPtr->_cury].EndCol, WinPtr->_curx - 1);
X      TmpAttrs = WinPtr->_attrs;
X      wattrset(WinPtr, 0); /* better to call wattrset in case I change attrs */
X      wclrtoeol(WinPtr);
X      wattrset(WinPtr, TmpAttrs);
X      if(PWinStat)
X	PWinStat->LnArry[WinPtr->_cury+WinPtr->_begy].EndCol=max(PWinStat->LnArry[WinPtr->_cury+WinPtr->_begy].EndCol,WinPtr->_curx+WinPtr->_begx-1);
X      WinPtr->_curx = 0;
X      WinPtr->_cury++;
X      if(WinPtr->_cury > WinStat->ScrollBot) {
X	if(WinPtr->_scroll)
X	  scroll(WinPtr);
X	WinPtr->_cury = WinStat->ScrollBot;
X      }
X      if(*(Str + 1)) {  /* If there is more then touch this line too */
X	WinStat->LnArry[WinPtr->_cury].Touched = TRUE;
X	WinStat->LnArry[WinPtr->_cury].StartCol = min(WinStat->LnArry[WinPtr->_cury].StartCol, WinPtr->_curx);
X	if(PWinStat) {
X	  PWinStat->LnArry[WinPtr->_cury+WinPtr->_begy].Touched = TRUE;
X	  PWinStat->LnArry[WinPtr->_cury+WinPtr->_begy].StartCol = min(PWinStat->LnArry[WinPtr->_cury+WinPtr->_begy].StartCol, WinPtr->_curx+WinPtr->_begx);
X	}
X      }
X      break;
X    default:
X      WinStat->LnArry[WinPtr->_cury].Line[WinPtr->_curx] = *Str;
X      WinStat->LnArry[WinPtr->_cury].ATTRS[WinPtr->_curx] = WinPtr->_attrs;
X      WinPtr->_curx++;
X      break;
X    }
X    /* If hit right edge of window then increment _cury */
X    if(WinPtr->_curx > WinPtr-> _maxx) {
X      WinStat->LnArry[WinPtr->_cury].EndCol = max(WinStat->LnArry[WinPtr->_cury].EndCol, WinPtr->_curx - 1);
X      WinPtr->_curx = 0;
X      WinPtr->_cury++;
X      if(WinPtr->_cury > WinStat->ScrollBot) {
X	if(WinPtr->_scroll)
X	  scroll(WinPtr);
X	WinPtr->_cury = WinStat->ScrollBot;
X      }
X      if(WinPtr->_cury > WinPtr->_maxy)
X	WinPtr->_cury = WinPtr->_maxy;
X      if(*(Str + 1)) {  /* If there is more then touch this line too */
X	WinStat->LnArry[WinPtr->_cury].Touched = TRUE;
X	WinStat->LnArry[WinPtr->_cury].StartCol = min(WinStat->LnArry[WinPtr->_cury].StartCol, WinPtr->_curx);
X	if(PWinStat) {
X	  PWinStat->LnArry[WinPtr->_cury+WinPtr->_begy].Touched = TRUE;
X	  PWinStat->LnArry[WinPtr->_cury+WinPtr->_begy].StartCol = min(PWinStat->LnArry[WinPtr->_cury+WinPtr->_begy].StartCol, WinPtr->_curx+WinPtr->_begx);
X	}
X      }
X    }
X    Str++;
X  }
X  WinStat->LnArry[WinPtr->_cury].EndCol = max(WinStat->LnArry[WinPtr->_cury].EndCol, WinPtr->_curx - 1);
X  if(PWinStat)
X    PWinStat->LnArry[WinPtr->_cury+WinPtr->_begy].EndCol = max(PWinStat->LnArry[WinPtr->_cury+WinPtr->_begy].EndCol, WinPtr->_curx+WinPtr->_begx-1);
X  return OK;
X}
X
Xwaddch(WinPtr, c)
X     WINDOW *WinPtr;
X     char c;
X{
X  char *str = " ";
X  
X  *str = c;
X  return waddstr(WinPtr, str);
X}
X
Xwinsch(WinPtr, c)
X     WINDOW *WinPtr;
X     char c;
X{
X  int i;
X  struct WindowState *WinStat;
X  
X  if(!(WinStat = (struct WindowState *)WinPtr->_WinStat))
X    return ERR;
X  
X  /* shuffle line along to the right */
X  for (i = WinPtr->_maxx; i > WinPtr->_curx; i--)
X    WinStat->LnArry[WinPtr->_cury].Line[i] = WinStat->LnArry[WinPtr->_cury].Line[i-1];
X  WinStat->LnArry[WinPtr->_cury].Line[i] = c;
X  WinStat->LnArry[WinPtr->_cury].StartCol = min(WinStat->LnArry[WinPtr->_cury].StartCol, WinPtr->_curx);
X  WinStat->LnArry[WinPtr->_cury].EndCol = WinPtr->_maxx;
X  WinStat->LnArry[WinPtr->_cury].Touched = TRUE;
X  
X  return OK;
X}
X
Xwdelch(WinPtr)
X     WINDOW *WinPtr;
X{
X  int i;
X  struct WindowState *WinStat;
X  
X  if(!(WinStat = (struct WindowState *)WinPtr->_WinStat))
X    return ERR;
X  
X  /* shuffle line along to the left */
X  for (i = WinPtr->_curx; i < WinPtr->_maxx; i++)
X    WinStat->LnArry[WinPtr->_cury].Line[i] = WinStat->LnArry[WinPtr->_cury].Line[i+1];
X  WinStat->LnArry[WinPtr->_cury].Line[i] = ' ';  /* Blank last char */
X  WinStat->LnArry[WinPtr->_cury].StartCol = min(WinStat->LnArry[WinPtr->_cury].StartCol, WinPtr->_curx);
X  WinStat->LnArry[WinPtr->_cury].EndCol = WinPtr->_maxx;
X  WinStat->LnArry[WinPtr->_cury].Touched = TRUE;
X  
X  return OK;
X}
X
Xwclear(WinPtr)
X     WINDOW *WinPtr;
X{
X  int Line, Col;
X  struct WindowState *WinStat;
X  
X  if(!(CursesFlags & CFLAG_INITSCR))  /* Haven't called initscr() */
X    return ERR;
X  
X  if(!(WinStat = (struct WindowState *)WinPtr->_WinStat))
X    return ERR;
X  
X  for(Line=0; Line<WinStat->NLines; Line++) {
X    memset(WinStat->LnArry[Line].Line, ' ', WinPtr->_maxx + 1);
X    memset(WinStat->LnArry[Line].LRLine, ' ', WinPtr->_maxx + 1);
X    for(Col = 0; Col <= WinPtr->_maxx; Col++) {
X      WinStat->LnArry[Line].ATTRS[Col] = WinPtr->_attrs;
X      WinStat->LnArry[Line].LRATTRS[Col] = WinPtr->_attrs;
X    }
X    WinStat->LnArry[Line].Touched = FALSE;
X    WinStat->LnArry[Line].StartCol = WinPtr->_maxx;
X    WinStat->LnArry[Line].EndCol = 0;
X  }
X  WinPtr->_curx = 0;
X  WinPtr->_cury = 0;
X  WinPtr->_cls = TRUE;
X  return OK;
X}
X
Xwerase(WinPtr)
X     WINDOW *WinPtr;
X{
X  int Line, Col;
X  struct WindowState *WinStat;
X  
X  if(!(CursesFlags & CFLAG_INITSCR))  /* Haven't called initscr() */
X    return ERR;
X  
X  if(!(WinStat = (struct WindowState *)WinPtr->_WinStat))
X    return ERR;
X  
X  /* Blank screen image */
X  for(Line=0; Line<WinStat->NLines; Line++) {
X    memset(WinStat->LnArry[Line].Line, ' ', WinPtr->_maxx + 1);
X    for(Col = 0; Col <= WinPtr->_maxx; Col++)
X      WinStat->LnArry[Line].ATTRS[Col] = WinPtr->_attrs;
X    WinStat->LnArry[Line].Touched = TRUE;
X    WinStat->LnArry[Line].StartCol = 0;
X    WinStat->LnArry[Line].EndCol = WinPtr->_maxx;
X  }
X  WinPtr->_curx = 0;
X  WinPtr->_cury = 0;
X  return OK;
X}
X
Xclearok(WinPtr, flag)
X     WINDOW *WinPtr;
X     int flag;
X{
X  if(!(CursesFlags & CFLAG_INITSCR))  /* Haven't called initscr() */
X    return ERR;
X  
X  WinPtr->_clear = (flag) ? TRUE : FALSE;
X  
X  return OK;
X}
X
Xwclrtoeol(WinPtr)
X     WINDOW *WinPtr;
X{
X  short x, y;
X  int len;
X  char Buffer[100];
X  
X  if(!(CursesFlags & CFLAG_INITSCR))  /* Haven't called initscr() */
X    return ERR;
X  x = WinPtr->_curx;
X  y = WinPtr->_cury;
X  
X  len = WinPtr->_maxx - WinPtr->_curx + 1;
X  memset(Buffer, ' ', len);
X  Buffer[len] = '\0';
X  
X  waddstr(WinPtr, Buffer);
X  wmove(WinPtr, y, x);
X  
X  return OK;
X}
X
Xwclrtobot(WinPtr)
X     WINDOW *WinPtr;
X{
X  short x, y;
X  int i;
X  
X  if(!(CursesFlags & CFLAG_INITSCR))  /* Haven't called initscr() */
X    return ERR;
X  x = WinPtr->_curx;
X  y = WinPtr->_cury;
X  
X  wclrtoeol(WinPtr);
X  for(i = WinPtr->_cury + 1; i <= WinPtr->_maxy; i++) {
X    wmove(WinPtr, i, 0);
X    wclrtoeol(WinPtr);
X  }
X  wmove(WinPtr, y, x);
X  
X  return OK;
X}
X
Xstatic int GetNextChar(WinPtr)
X     WINDOW *WinPtr;
X{
X  static unsigned char buffer[RAWBUFSIZ], BufPos = 0, NumChars = 0;
X  int Class, i;
X  struct IntuiMessage *Message;
X  static struct InputEvent ievent = { NULL, IECLASS_RAWKEY, 0, 0, 0 };
X  
X  if(BufPos < NumChars)  /* If we still hav some chars then return next */
X    return (int)buffer[BufPos++];
X  
X  while (BufPos == NumChars) {
X    /* Get message if there is one allready queued */
X    Message = (struct IntuiMessage *)GetMsg(CursesWindow->UserPort);
X    if(!Message) {
X      /* Nuffin yet */
X      if(WinPtr->_nodelay)  /* If non-blocking return ERR */
X	return ERR;
X      else {    /* Wait for character */
X	Wait(1<<CursesWindow->UserPort->mp_SigBit);
X	Message = (struct IntuiMessage *)GetMsg(CursesWindow->UserPort);
X      }
X    }
X    if(!Message)  /* Try again */
X      continue;
X    
X    Class = Message->Class;
X    switch(Class) {
X    case RAWKEY:
X      BufPos = 0;
X      ievent.ie_Code = Message->Code;
X      ievent.ie_Qualifier = Message->Qualifier;
X      ievent.ie_position.ie_addr = *((APTR*)Message->IAddress);
X      NumChars = RawKeyConvert(&ievent, buffer, RAWBUFSIZ, 0L);
X      ReplyMsg((struct Message *)Message);
X      if(!NumChars)  /* If no characters then try again */
X	break;
X      if(CursesFlags & CFLAG_ECHO)
X	for(i=0; i<NumChars; i++)
X	  DoEcho(WinPtr, buffer[i]);
X      /* Translate id keypad set to TRUE */
X      if(WinPtr->_use_keypad) {
X	switch(NumChars) {
X	case 1:
X	  NumChars = 0;  /* Translation will use up all chars */
X	  return (int)buffer[0];
X	case 2:    /* ARROW KEY */
X	  NumChars = 0;  /* Translation will use up all chars */
X	  if(buffer[0] != 155)
X	    return -1;
X	  switch(buffer[1]) {
X	  case 65: return KEY_UP;
X	  case 66: return KEY_DOWN;
X	  case 67: return KEY_RIGHT;
X	  case 68: return KEY_LEFT;
X	  default: return -1;
X	  }
X	case 3:    /* FUNCTION KEY */
X	  NumChars = 0;  /* Translation will use up all chars */
X	  if(buffer[0] != 155)
X	    return -1;
X	  if(buffer[2] != 126)
X	    return -1;
X	  if(buffer[1] == 63)
X	    return KEY_HELP;
X	  return KEY_F0 + (buffer[1] - 48);  /* KEY_F0 = F1 */
X	default:
X	  NumChars = 0;  /* Translation will use up all chars */
X	  return -1;
X	}
X      }
X      break;
X    default:
X      ReplyMsg((struct Message *)Message);
X      break;
X    }
X  }
X  return (int)buffer[BufPos++];
X}
X
Xflushinp()
X{
X  GetchRPos = 0;
X  GetchWPos = 0;
X  return OK;
X}
X
Xwgetch(WinPtr)
X     WINDOW *WinPtr;
X{
X  static int buffer[256];  /* Cyclic buffer */
X  static unsigned char forward = FALSE;
X  int Ret;
X  
X  if(!(CursesFlags & CFLAG_INITSCR))  /* Haven't called initscr() */
X    return ERR;
X  
X  while(GetchRPos == GetchWPos || (!(CursesFlags & CFLAG_CBREAK) && !forward)) {
X    if(WinPtr->_nodelay)
X      return GetNextChar(WinPtr);
X    if((Ret = GetNextChar(WinPtr)) >= 0)
X      buffer[GetchWPos++] = Ret;
X    if(Ret == (int)'\r')
X      forward = TRUE;
X  }
X  if(buffer[GetchRPos] == '\r') {
X    buffer[GetchRPos] = '\n';
X    forward = FALSE;
X  }
X  return((int)buffer[GetchRPos++]);
X}
X
Xwgetstr(WinPtr, ptr)
X     WINDOW *WinPtr;
X     char *ptr;
X{
X  char done = FALSE, *BuffStart;
X  unsigned char TempFlag;  /* Used to restore flags after */
X  
X  if(!(CursesFlags & CFLAG_INITSCR))  /* Haven't called initscr() */
X    return ERR;
X  
X  BuffStart = ptr;
X  
X  /* Will need to be in CBREAK mode for this */
X  TempFlag = CursesFlags;
X  CursesFlags |= CFLAG_CBREAK;
X  while(!done) {
X    switch(*ptr = wgetch(WinPtr)) {
X    case -1:  /* wgetch() returned ERROR */
X      *ptr = '\0';
X      CursesFlags = TempFlag;
X      return -1;
X    case '\n':
X    case '\r':
X      *ptr = '\0';
X      done = TRUE;
X      break;
X    case '\b':
X      if(--ptr < BuffStart)  /* Don't move before start */
X	ptr = BuffStart;
X      else if(CursesFlags & CFLAG_ECHO) {
X	/* Do BS SP BS processing */
X	mvcur(CursorLine, CursorCol, CursorLine, CursorCol - 1);  /* BS */
X	DoEcho(WinPtr, ' ');          /* SP */
X	mvcur(CursorLine, CursorCol, CursorLine, CursorCol - 1);  /* BS */
X      }
X      break;
X    default:
X      ptr++;
X      break;
X    }
X  }
X  CursesFlags = TempFlag;
X  return 0;
X}
X
Xwinch(WinPtr)
X     WINDOW *WinPtr;
X{
X  struct WindowState *WinStat;
X  
X  if(!(CursesFlags & CFLAG_INITSCR))  /* Haven't called initscr() */
X    return ERR;
X  
X  if(!(WinStat = (struct WindowState *)WinPtr->_WinStat))
X    return ERR;
X  
X  return (int)WinStat->LnArry[WinPtr->_cury].Line[WinPtr->_curx];
X}
X
Xstatic void DoEcho(WinPtr, c)
X     WINDOW *WinPtr;
X     char c;
X{
X  short x, y;
X  struct WindowState *WinStat;
X  
X  if(!(WinStat = (struct WindowState *)WinPtr->_WinStat))
X    return;
X  
X  if(c == BS || c == CR)        /* Don't echo Backspace or Return */
X    return;
X  
X  x = CursorCol * 8;
X  y = 6 + CursorLine * 8;
X  ZapCursor();
X  SetDrMd(RPort, JAM2);
X  SetAPen(RPort, WinPtr->_attrs & 0x0f);
X  Move(RPort, x, y);
X  Text(RPort, &c, 1);
X  DrawCursor();
X  /* Update curscr */
X  if(WinPtr != curscr) {
X    wmove(curscr, CursorLine, CursorCol);
X    waddch(curscr, c);
X  }
X  /* Update Line structure */
X  WinStat->LnArry[CursorLine-WinPtr->_begy].Line[CursorCol-WinPtr->_begx] = c;
X  WinStat->LnArry[CursorLine-WinPtr->_begy].LRLine[CursorCol-WinPtr->_begx] = c;
X  WinStat->LnArry[CursorLine-WinPtr->_begy].ATTRS[CursorCol-WinPtr->_begx] = WinPtr->_attrs;
X  WinStat->LnArry[CursorLine-WinPtr->_begy].LRATTRS[CursorCol-WinPtr->_begx] = WinPtr->_attrs;
X  /* Move current position one to the right */
X  if(++WinPtr->_curx > WinPtr->_maxx)
X    WinPtr->_curx = WinPtr->_maxx;
X  mvcur(CursorLine, CursorCol, CursorLine, CursorCol + 1);
X}
X
Xwmove(WinPtr, Line, Col)
X     WINDOW *WinPtr;
X     short Line, Col;
X{
X  if(!(CursesFlags & CFLAG_INITSCR))  /* Haven't called initscr() */
X    return ERR;
X  
X  if(Line<0 || Line>WinPtr->_maxy)
X    return ERR;
X  if(Col<0 || Col>WinPtr->_maxx)
X    return ERR;
X  WinPtr -> _cury = Line;
X  WinPtr -> _curx = Col;
X  WinPtr -> _flags |= CWF_MOVED;
X  return OK;
X}
X
Xmvcur(CurLine, CurCol, NewLine, NewCol)
X     int CurLine, CurCol, NewLine, NewCol;
X{
X  /* Could check CurLine and CurCol but this would make it fail too often */
X  ZapCursor();
X  CursorLine = NewLine;
X  CursorCol = NewCol;
X  DrawCursor();
X  return OK;
X}
X
Xprintw(fmt, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9)
X     char *fmt;
X     double A0, A1, A2, A3, A4, A5, A6, A7, A8, A9;
X{
X  int Ret;
X  char buffer[BUFSIZ];
X  
X  Ret = sprintf(buffer, fmt, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9);
X  waddstr(stdscr, buffer);
X  return Ret;
X}
X
Xwprintw(WinPtr, fmt, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9)
X     WINDOW *WinPtr;
X     char *fmt;
X     double A0, A1, A2, A3, A4, A5, A6, A7, A8, A9;
X{
X  int Ret;
X  char buffer[BUFSIZ];
X  
X  Ret = sprintf(buffer, fmt, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9);
X  waddstr(WinPtr, buffer);
X  return Ret;
X}
X
Xmvprintw(Line, Col, fmt, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9)
X     short Line, Col;
X     char *fmt;
X     double A0, A1, A2, A3, A4, A5, A6, A7, A8, A9;
X{
X  int Ret;
X  char buffer[BUFSIZ];
X  
X  Ret = sprintf(buffer, fmt, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9);
X  wmove(stdscr, Line, Col);
X  waddstr(stdscr, buffer);
X  return Ret;
X}
X
Xmvwprintw(WinPtr, Line, Col, fmt, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9)
X     WINDOW *WinPtr;
X     short Line, Col;
X     char *fmt;
X     double A0, A1, A2, A3, A4, A5, A6, A7, A8, A9;
X{
X  int Ret;
X  char buffer[BUFSIZ];
X  
X  Ret = sprintf(buffer, fmt, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9);
X  wmove(WinPtr, Line, Col);
X  waddstr(WinPtr, buffer);
X  return Ret;
X}
X
Xwrefresh(WinPtr)
X     WINDOW *WinPtr;
X{
X  int i, j;
X  unsigned long style;
X  short Line;
X  struct WindowState *WinStat;
X  char Buffer[BUFSIZ];
X  void Optimise();
X  
X  if(WinPtr == curscr)
X    touchwin(WinPtr);
X  if(!(WinStat = (struct WindowState *)WinPtr->_WinStat))
X    return ERR;
X  ZapCursor();
X  /*
X   *  It is possible for no printing since last refresh, but for
X   *  a move to have been done...
X   */
X  if(WinPtr->_flags & CWF_MOVED) {
X    WinPtr->_flags &= ~CWF_MOVED;
X    CursorLine = WinPtr->_cury + WinPtr->_begy;
X    CursorCol = WinPtr->_curx + WinPtr->_begx;
X  }
X  /*
X   *  If clearok has been called, then clear on every refresh.
X   */
X  if(WinPtr->_clear || WinPtr->_cls) {
X    WinPtr->_cls = FALSE;
X    SetAPen(RPort, 0);
X    SetDrMd(RPort, JAM2);
X    RectFill(RPort, (WinPtr->_begx * 8), (WinPtr->_begy * 8),
X	     ((WinPtr->_begx + WinPtr->_maxx) * 8) + 7,
X	     ((WinPtr->_begy + WinPtr->_maxy) * 8 + 7));
X  }
X  if(CursesFlags & CFLAG_CURSOR) {
X    CursorLine = WinPtr->_cury + WinPtr->_begy;
X    CursorCol = WinPtr->_curx + WinPtr->_begx;
X  }
X  for(Line=0; Line<WinStat->NLines; Line++) {
X    /* if clearok set then must refresh everything */
X    if(WinPtr->_clear) {
X      memset(WinStat->LnArry[Line].LRLine, ' ', WinPtr->_maxx+1);
X      WinStat->LnArry[Line].Touched = TRUE;
X      WinStat->LnArry[Line].StartCol = 0;
X      WinStat->LnArry[Line].EndCol = WinPtr->_maxx;
X    }
X    Optimise(&WinStat->LnArry[Line]);
X    if(WinStat->LnArry[Line].Touched) {
X      j = WinStat->LnArry[Line].StartCol;
X      for(i=WinStat->LnArry[Line].StartCol + 1; i<=WinStat->LnArry[Line].EndCol; i++) {
X	if(WinStat->LnArry[Line].ATTRS[i] != WinStat->LnArry[Line].ATTRS[j]) {
X	  /* Print what we've got */
X	  SetAPen(RPort, WinStat->LnArry[Line].ATTRS[j] & 017);
X	  if(WinStat->LnArry[Line].ATTRS[j] & (A_REVERSE | A_STANDOUT))
X	    SetDrMd(RPort, JAM2|INVERSVID);
X	  else
X	    SetDrMd(RPort, JAM2);
X	  style = FS_NORMAL;
X	  if(WinStat->LnArry[Line].ATTRS[j] & A_BOLD)
X	    style |= FSF_BOLD;
X	  if(WinStat->LnArry[Line].ATTRS[j] & A_UNDERLINE)
X	    style |= FSF_UNDERLINED;
X	  SetSoftStyle(RPort, style, ~0L);
X	  Move(RPort, (j+WinPtr->_begx) * 8, 6 + (Line+WinPtr->_begy) * 8);
X	  Text(RPort, &WinStat->LnArry[Line].Line[j], i-j);
X	  /*
X	   *  Update the record of the current screen state.
X	   */
X	  if(WinPtr != curscr) {
X	    wmove(curscr, Line+WinPtr->_begy, j+WinPtr->_begx);
X	    memcpy(Buffer, &WinStat->LnArry[Line].Line[j], i-j);
X	    Buffer[i-j] = '\0';
X	    waddstr(curscr, Buffer);
X	  }
X	  j = i;
X	}
X      }
X      if(j < i) {
X	SetAPen(RPort, WinStat->LnArry[Line].ATTRS[j] & 017);
X	if(WinStat->LnArry[Line].ATTRS[j] & (A_STANDOUT | A_REVERSE))
X	  SetDrMd(RPort, JAM2|INVERSVID);
X	else
X	  SetDrMd(RPort, JAM2);
X	style = FS_NORMAL;
X	if(WinStat->LnArry[Line].ATTRS[j] & A_BOLD)
X	  style |= FSF_BOLD;
X	if(WinStat->LnArry[Line].ATTRS[j] & A_UNDERLINE)
X	  style |= FSF_UNDERLINED;
X	SetSoftStyle(RPort, style, ~0L);
X	Move(RPort, (j+WinPtr->_begx) * 8, 6 + (Line+WinPtr->_begy) * 8);
X	Text(RPort, &(WinStat->LnArry[Line].Line[j]), i-j);
X	/*
X	 *  Update the record of the current screen state.
X	 */
X	if(WinPtr != curscr) {
X	  wmove(curscr, Line+WinPtr->_begy, j+WinPtr->_begx);
X	  memcpy(Buffer, &WinStat->LnArry[Line].Line[j], i-j);
X	  Buffer[i-j] = '\0';
X	  waddstr(curscr, Buffer);
X	}
X      }
X      WinStat->LnArry[Line].Touched = FALSE;
X      WinStat->LnArry[Line].StartCol = WinPtr->_maxx;
X      WinStat->LnArry[Line].EndCol = 0;
X    }
X    /*
X     *  Copy line and attrs to LR for Optimise code
X     */
X    memcpy(WinStat->LnArry[Line].LRLine, WinStat->LnArry[Line].Line, WinPtr->_maxx+1);
X    memcpy(WinStat->LnArry[Line].LRATTRS, WinStat->LnArry[Line].ATTRS, sizeof(short) * (WinPtr->_maxx+1));
X  }
X  DrawCursor();
X  return OK;
X}
X
Xstatic void ToggleCursor(Line, Col)
X{
X  SetDrMd(RPort, JAM2 | INVERSVID | COMPLEMENT);
X  Move(RPort, Col*8, 6 + Line*8);
X  Text(RPort, " ", 1);
X}
X
Xstatic void
X  ZapCursor()
X{
X  /* If there was a cursor then blank it */
X  if(LCursorCol >= 0 && LCursorLine >= 0)
X    ToggleCursor(LCursorLine, LCursorCol);
X  
X  LCursorCol = LCursorLine = -1;
X}
X
Xstatic void DrawCursor()
X{
X  /* Draw cursor */
X  if(CursesFlags & CFLAG_CURSOR)
X    ToggleCursor(CursorLine, CursorCol);
X  
X  if(CursesFlags & CFLAG_CURSOR) {
X    LCursorCol = CursorCol;
X    LCursorLine = CursorLine;
X  } else {
X    LCursorCol = -1;
X    LCursorLine = -1;
X  }
X}
X
Xscanw(fmt, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9)
X     char *fmt;
X     long A0, A1, A2, A3, A4, A5, A6, A7, A8, A9;
X{
X  char buffer[BUFSIZ];
X  
X  wgetstr(stdscr, buffer);
X  return sscanf(buffer, fmt, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9);
X}
X
Xwscanw(WinPtr, fmt, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9)
X     WINDOW *WinPtr;
X     char *fmt;
X     long A0, A1, A2, A3, A4, A5, A6, A7, A8, A9;
X{
X  char buffer[BUFSIZ];
X  
X  wgetstr(WinPtr, buffer);
X  return sscanf(buffer, fmt, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9);
X}
X
Xmvscanw(Line, Col, fmt, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9)
X     short Line, Col;
X     char *fmt;
X     long A0, A1, A2, A3, A4, A5, A6, A7, A8, A9;
X{
X  char buffer[BUFSIZ];
X  
X  wmove(stdscr, Line, Col);
X  wgetstr(stdscr, buffer);
X  return sscanf(buffer, fmt, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9);
X}
X
Xmvwscanw(WinPtr, Line, Col, fmt, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9)
X     WINDOW *WinPtr;
X     short Line, Col;
X     char *fmt;
X     long A0, A1, A2, A3, A4, A5, A6, A7, A8, A9;
X{
X  char buffer[BUFSIZ];
X  
X  wmove(WinPtr, Line, Col);
X  wgetstr(WinPtr, buffer);
X  return sscanf(buffer, fmt, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9);
X}
X
Xwstandout(WinPtr)
X     WINDOW *WinPtr;
X{
X  if(!(CursesFlags & CFLAG_INITSCR))  /* Haven't called initscr() */
X    return ERR;
X  
X  WinPtr->_attrs |= A_STANDOUT;
X}
X
Xwstandend(WinPtr)
X     WINDOW *WinPtr;
X{
X  if(!(CursesFlags & CFLAG_INITSCR))  /* Haven't called initscr() */
X    return ERR;
X  
X  WinPtr->_attrs &= ~A_STANDOUT;
X}
X
Xwattrset(WinPtr, attr)
X     WINDOW *WinPtr;
X     short attr;
X{
X  if(!(CursesFlags & CFLAG_INITSCR))  /* Haven't called initscr() */
X    return ERR;
X  
X  /*
X   *  Older code may inadvertently reset the attributes and set the
X   *  forground colour to 0, in this case, set it to white.
X   */
X  if(!(attr & 017))
X    attr |= COLOR_WHITE;
X  
X  WinPtr->_attrs = attr;
X  return OK;
X}
X
Xwattron(WinPtr, attr)
X     WINDOW *WinPtr;
X     short attr;
X{
X  if(!(CursesFlags & CFLAG_INITSCR))  /* Haven't called initscr() */
X    return ERR;
X  
X  /* If attributes contain a colour change then mask off old colour */
X  if(attr & 017)
X    WinPtr->_attrs &= ~017;
X  
X  WinPtr->_attrs |= attr;
X  return OK;
X}
X
Xwattroff(WinPtr, attr)
X     WINDOW *WinPtr;
X     short attr;
X{
X  if(!(CursesFlags & CFLAG_INITSCR))  /* Haven't called initscr() */
X    return ERR;
X  
X  WinPtr->_attrs &= ~attr;
X  return OK;
X}
X
Xcbreak()
X{
X  if(!(CursesFlags & CFLAG_INITSCR))  /* Haven't called initscr() */
X    return ERR;
X  
X  CursesFlags |= CFLAG_CBREAK;
X  return OK;
X}
X
Xnocbreak()
X{
X  if(!(CursesFlags & CFLAG_INITSCR))  /* Haven't called initscr() */
X    return ERR;
X  
X  CursesFlags &= ~CFLAG_CBREAK;
X  return OK;
X}
X
Xraw()
X{
X  if(!(CursesFlags & CFLAG_INITSCR))  /* Haven't called initscr() */
X    return ERR;
X  
X  CursesFlags |= CFLAG_CBREAK;
X  return OK;
X}
X
Xnoraw()
X{
X  if(!(CursesFlags & CFLAG_INITSCR))  /* Haven't called initscr() */
X    return ERR;
X  
X  CursesFlags &= ~CFLAG_CBREAK;
X  return OK;
X}
X
Xidlok(WinPtr, flag)
X     WINDOW *WinPtr;
X     int flag;
X{
X  /* This function is to enable hardware insert/delete line */
X  return OK;
X}
X
Xwinsertln(WinPtr)
X     WINDOW *WinPtr;
X{
X  Scroll(WinPtr, WinPtr->_cury, WinPtr->_maxy, SCROLL_DOWN);
X  return OK;
X}
X
Xwdeleteln(WinPtr)
X     WINDOW *WinPtr;
X{
X  Scroll(WinPtr, WinPtr->_cury, WinPtr->_maxy, SCROLL_UP);
X  return OK;
X}
X
Xnodelay(WinPtr, flag)
X     WINDOW *WinPtr;
X     int flag;
X{
X  if(!(CursesFlags & CFLAG_INITSCR))  /* Haven't called initscr() */
X    return ERR;
X  
X  WinPtr->_nodelay = flag;
X  return OK;
X}
X
Xecho()
X{
X  if(!(CursesFlags & CFLAG_INITSCR))  /* Haven't called initscr() */
X    return ERR;
X  
X  CursesFlags |= CFLAG_ECHO;
X  return OK;
X}
X
Xnoecho()
X{
X  if(!(CursesFlags & CFLAG_INITSCR))  /* Haven't called initscr() */
X    return ERR;
X  
X  CursesFlags &= ~CFLAG_ECHO;
X  return OK;
X}
X
Xkeypad(WinPtr, flag)
X     WINDOW *WinPtr;
X     char flag;
X{
X  if(!(CursesFlags & CFLAG_INITSCR))  /* Haven't called initscr() */
X    return ERR;
X  
X  WinPtr->_use_keypad = flag?TRUE:FALSE;
X  
X  return OK;
X}
X
Xbeep()
X{
X  if(!(CursesFlags & CFLAG_INITSCR))  /* Haven't called initscr() */
X    return ERR;
X  
X  AIOptr = (struct IOAudio *) AllocMem(sizeof(struct IOAudio), MEMF_CHIP|MEMF_PUBLIC);
X  if(!AIOptr)
X    exit(1);
X  
X  port = (struct MsgPort *)CreatePort(0, 0);
X  if(!port) {
X    FreeMem(AIOptr, sizeof(struct IOAudio));
X    return ERR;
X  }
X  
X  AIOptr->ioa_Request.io_Message.mn_ReplyPort = port;
X  AIOptr->ioa_Request.io_Message.mn_Node.ln_Pri = 0;
X  AIOptr->ioa_Request.io_Command = ADCMD_ALLOCATE;
X  AIOptr->ioa_Request.io_Flags = ADIOF_NOWAIT;
X  AIOptr->ioa_AllocKey = 0;
X  AIOptr->ioa_Data = whichannel;
X  AIOptr->ioa_Length = sizeof(whichannel);
X  
X  device = OpenDevice("audio.device", 0L, (struct IORequest *)AIOptr, 0L);
X  if(device) {
X    printf("Curses beep() - Can't open Audio Device\n");
X    FreeMem(AIOptr, sizeof(struct IOAudio));
X    return ERR;
X  }
X  
X  sound_data = (UBYTE *) AllocMem(SOUNDLENGTH, MEMF_CHIP|MEMF_PUBLIC);
X  if(!sound_data) {
X    FreeMem(AIOptr, sizeof(struct IOAudio));
X    return ERR;
X  }
X  
X  sound_data[0]=127;
X  sound_data[1]=-127;
X  
X  AIOptr->ioa_Request.io_Message.mn_ReplyPort = port;
X  AIOptr->ioa_Request.io_Command = CMD_WRITE;
X  AIOptr->ioa_Request.io_Flags = ADIOF_PERVOL;
X  AIOptr->ioa_Data = sound_data;
X  AIOptr->ioa_Cycles = 200;
X  AIOptr->ioa_Length = SOUNDLENGTH;
X  AIOptr->ioa_Period = 2000;
X  AIOptr->ioa_Volume = 64;
X  
X  BeginIO((struct IORequest *)AIOptr);
X  WaitIO((struct IORequest *)AIOptr);
X  
X  FreeMem(sound_data, SOUNDLENGTH);
X  DeletePort(port);
X  CloseDevice((struct IORequest *)AIOptr);
X  FreeMem(AIOptr, sizeof(struct IOAudio));
X}
X
Xflash()
X{
X  if(!(CursesFlags & CFLAG_INITSCR))  /* Haven't called initscr() */
X    return ERR;
X  
X  DisplayBeep(CursesScreen);
X}
X
Xleaveok(WinPtr, flag)
X     WINDOW *WinPtr;
X     int flag;
X{
X  if(!(CursesFlags & CFLAG_INITSCR))  /* Haven't called initscr() */
X    return ERR;
X  
X  if(flag) {
X    CursorCol = CursorLine = -1;
X    CursesFlags &= ~CFLAG_CURSOR;
X  } else {
X    CursesFlags |= CFLAG_CURSOR;
X  }
X  return OK;
X}
X
Xresetty()
X{
X  return OK;
X}
X
Xsavetty()
X{
X  return OK;
X}
X
Xresetterm()
X{
X  return OK;
X}
X
Xfixterm()
X{
X  return OK;
X}
X
Xsaveterm()
X{
X  return OK;
X}
X
Xbaudrate()
X{
X  return 9600;
X}
X
Xnl()
X{
X  CursesFlags |= CFLAG_NLCR;
X  return OK;
X}
X
Xnonl()
X{
X  CursesFlags &= ~CFLAG_NLCR;
X  return OK;
X}
X
Xcrmode()
X{
X  return (cbreak());
X}
X
Xnocrmode()
X{
X  return (nocbreak());
X}
X
Xbox(WinPtr, vert, hor)
X     WINDOW *WinPtr;
X     char vert, hor;
X{
X  int i;
X  short CurY, CurX;
X  
X  CurY = WinPtr->_cury;
X  CurX = WinPtr->_curx;
X  
X  if(vert < 32 || vert > 126)
X    vert = '|';
X  if(hor < 32 || hor > 126)
X    hor = '-';
X  
X  for(i=0; i<=WinPtr->_maxx; i++) {
X    mvwaddch(WinPtr, 0, i, hor);  /* Top horizontal */
X    mvwaddch(WinPtr, WinPtr->_maxy, i, hor);  /* Bottom horizontal */
X  }
X  for(i=1; i<WinPtr->_maxy; i++) {
X    mvwaddch(WinPtr, i, 0, vert);  /* Left vertical */
X    mvwaddch(WinPtr, i, WinPtr->_maxx, vert);  /* Right vertical */
X  }
X  WinPtr -> _cury = CurY;
X  WinPtr -> _curx = CurX;
X  return OK;
X}
X
XWINDOW *subwin(Orig, NLines, NCols, StartLine, StartCol)
X     WINDOW *Orig;
X     unsigned int NLines, NCols, StartLine, StartCol;
X{
X  WINDOW *WinPtr, *CreatWindow();
X  
X  if(!(WinPtr = CreatWindow(NLines, NCols, StartLine, StartCol, Orig))) {
X    printf("WARNING - subwin() failed, returning stdscr !!\n");
X    return stdscr;  /* Failed */
X  }
X  return WinPtr;
X}
X
XWINDOW *newwin(NLines, NCols, StartLine, StartCol)
X     unsigned int NLines, NCols, StartLine, StartCol;
X{
X  WINDOW *WinPtr, *CreatWindow();
X  
X  if(!(WinPtr = CreatWindow(NLines, NCols, StartLine, StartCol, NULL))) {
X    printf("WARNING - newwin() failed, returning stdscr !!\n");
X    return stdscr;  /* Failed */
X  }
X  wclear(WinPtr);
X  return WinPtr;
X}
X
X/* Orig is NULL and StartCol/Line are not used for newwin() calls */
Xstatic WINDOW *CreatWindow(NLines, NCols, StartLine, StartCol, Orig)
X     int NLines, NCols, StartLine, StartCol;
X     WINDOW *Orig;
X{
X  int Line, j;
X  struct WindowState *NewWinStat, *TmpWinPtr, *OrgWinStat = NULL;
X  char *malloc();
X  
X  /* If either are zero then make them max */
X  if(!NLines)
X    NLines = LINES - StartLine;
X  if(!NCols)
X    NCols = COLS - StartCol;
X  
X  if(NLines>LINES || NCols>COLS || StartLine>LINES || StartCol>COLS)
X    return (struct WINDOW *)NULL;
X  
X  if(StartLine < 0)
X    StartLine = 0;
X  if(StartCol < 0)
X    StartCol = 0;
X  if(Orig)
X    OrgWinStat = (struct WindowState *)Orig->_WinStat;
X  
X  /* Create a new WinStat structure */
X  if((NewWinStat=(struct WindowState *)malloc(sizeof(struct WindowState)))
X     == (struct WindowState *)NULL) {
X    fprintf(stderr, "CreatWindow() - Not enough memory\n");
X    return (struct WINDOW *)NULL;
X  }
X  NewWinStat->ParentWin = Orig;
X  NewWinStat->Next = (struct WindowState *)NULL;
X  NewWinStat->Prev = (struct WindowState *)NULL;
X  NewWinStat->ScrollTop = 0;
X  NewWinStat->ScrollBot = NLines - 1;
X  NewWinStat->NLines = NLines;
X  /* Allocate space for LnArry[] */
X  if(!(NewWinStat->LnArry = (struct LineElement *)malloc(sizeof(struct LineElement)*LINES))) {
X    fprintf(stderr, "CreatWindow() - Not enough memory\n");
X    return (struct WINDOW *)NULL;
X  }
X  /* Allocate space for Line, LRLine e.t.c */
X  for(Line = 0; Line < NLines; Line++) {
X    if(OrgWinStat) {  /* If this is a subwindow */
X      /* Set up pointers into parent window */
X      NewWinStat->LnArry[Line].Line =
X	&OrgWinStat->LnArry[Line+StartLine].Line[StartCol];
X      NewWinStat->LnArry[Line].LRLine =
X	&OrgWinStat->LnArry[Line+StartLine].LRLine[StartCol];
X      NewWinStat->LnArry[Line].ATTRS =
X	&OrgWinStat->LnArry[Line+StartLine].ATTRS[StartCol];
X      NewWinStat->LnArry[Line].LRATTRS =
X	&OrgWinStat->LnArry[Line+StartLine].LRATTRS[StartCol];
X    } else {  /* New window, allocate space for lines */
X      /* malloc lines and ATTRS */
X      if((NewWinStat->LnArry[Line].Line = malloc(NCols)) == NULL) {
X	fprintf(stderr, "CreatWindow() - Not enough memory\n");
X	return (struct WINDOW *)NULL;
X      }
X      if((NewWinStat->LnArry[Line].LRLine = malloc(NCols)) == NULL) {
X	fprintf(stderr, "CreatWindow() - Not enough memory\n");
X	return (struct WINDOW *)NULL;
X      }
X      if((NewWinStat->LnArry[Line].ATTRS =
X	  (short *)malloc(NCols*sizeof(short))) == NULL) {
X	fprintf(stderr, "CreatWindow() - Not enough memory\n");
X	return (struct WINDOW *)NULL;
X      }
X      if((NewWinStat->LnArry[Line].LRATTRS =
X	  (short *)malloc(NCols*sizeof(short))) == NULL) {
X	fprintf(stderr, "CreatWindow() - Not enough memory\n");
X	return (struct WINDOW *)NULL;
X      }
X      /* The optimiser will untouch any lines not used */
X      memset(NewWinStat->LnArry[Line].LRLine, ' ', NCols);
X      for(j=0; j<NCols; j++)
X	NewWinStat->LnArry[Line].LRATTRS[j] = A_NORMAL | COLOR_WHITE;
X    }
X    NewWinStat->LnArry[Line].Touched = FALSE;
X    NewWinStat->LnArry[Line].StartCol = NCols;
X    NewWinStat->LnArry[Line].EndCol = 0;
X  }
X  /* Add to Window Stat list */
X  if(HeadWindowList) {
X    TmpWinPtr = HeadWindowList;
X    while(TmpWinPtr->Next)
X      TmpWinPtr = TmpWinPtr->Next;
X    TmpWinPtr->Next = NewWinStat;
X    NewWinStat->Prev = TmpWinPtr;
X  } else {
X    /* This is the first window i.e. stdscr */
X    HeadWindowList = NewWinStat;
X  }
X  /* Initialise state of the window structure */
X  NewWinStat->Window._cury = 0;
X  NewWinStat->Window._curx = 0;
X  NewWinStat->Window._maxy = NLines - 1;
X  NewWinStat->Window._maxx = NCols - 1;
X  NewWinStat->Window._begy = StartLine;
X  NewWinStat->Window._begx = StartCol;
X  NewWinStat->Window._flags = 0;
X  NewWinStat->Window._attrs = A_NORMAL | COLOR_WHITE;
X  NewWinStat->Window._clear = FALSE;
X  NewWinStat->Window._cls = TRUE;
X  NewWinStat->Window._scroll = FALSE;
X  NewWinStat->Window._use_keypad = 0;
X  NewWinStat->Window._use_meta = 0;
X  NewWinStat->Window._nodelay = 0;
X  NewWinStat->Window._WinStat = (char *)NewWinStat;
X  
X  return &NewWinStat->Window;
X}
X
Xtouchwin(WinPtr)
X     WINDOW *WinPtr;
X{
X  struct WindowState *WinStat;
X  int Line;
X  
X  if(!(CursesFlags & CFLAG_INITSCR))
X    return ERR;
X  
X  if(!(WinStat = (struct WindowState *)WinPtr->_WinStat))
X    return ERR;
X  
X  for(Line=0; Line<WinStat->NLines; Line++) {
X    WinStat->LnArry[Line].Touched = TRUE;
X    /* Mark whole line as refreshable */
X    WinStat->LnArry[Line].StartCol = 0;
X    WinStat->LnArry[Line].EndCol = WinPtr->_maxx;
X    /* Dump optimisation */
X    memset(WinStat->LnArry[Line].LRLine, 0, WinPtr->_maxx+1);
X  }
X  return OK;
X}
X
Xdelwin(WinPtr)
X     WINDOW *WinPtr;
X{
X  struct WindowState *WinStat;
X  int LineNo;
X  
X  if(!(CursesFlags & CFLAG_INITSCR))
X    return ERR;
X  
X  if(!(WinStat = (struct WindowState *)WinPtr->_WinStat))
X    return ERR;
X  
X  if(!WinStat->ParentWin) {
X    /* If it's a real window, free up Line, LRLine, ATTRS, LRATTRS */
X    for(LineNo=0; LineNo<WinStat->NLines; LineNo++) {
X      free(WinStat->LnArry[LineNo].Line);
X      free(WinStat->LnArry[LineNo].LRLine);
X      free(WinStat->LnArry[LineNo].ATTRS);
X      free(WinStat->LnArry[LineNo].LRATTRS);
X    }
X  }
X  /* Free up LnArry[] */
X  free(WinStat->LnArry);
X  /* Remove the winstat from the list */
X  if(WinStat == HeadWindowList) { /* if this is first window (stdscr) */
X    HeadWindowList = WinStat->Next;
X    if(HeadWindowList)
X      HeadWindowList->Prev = (struct WindowState *)NULL;
X  } else {
X    if(WinStat->Next)
X      WinStat->Next->Prev = WinStat->Prev;
X    if(WinStat->Prev)
X      WinStat->Prev->Next = WinStat->Next;
X  }
X  /* Free the winstat */
X  free(WinStat);
X  return OK;
X}
X
X
Xmvwin(WinPtr, NewLine, NewCol)
X     WINDOW *WinPtr;
X     short NewLine, NewCol;
X{
X  if(!(CursesFlags & CFLAG_INITSCR))
X    return ERR;
X  
X  WinPtr->_begx = NewCol;
X  WinPtr->_begy = NewLine;
X  if(touchwin(WinPtr) == ERR)
X    return ERR;
X  return OK;
X}
X
Xscroll(WinPtr)
X     WINDOW *WinPtr;
X{
X  struct WindowState *WinStat;
X  
X  if(!(CursesFlags & CFLAG_INITSCR))
X    return ERR;
X  
X  if(!(WinStat = (struct WindowState *)WinPtr->_WinStat))
X    return ERR;
X  
X  Scroll(WinPtr, WinStat->ScrollTop, WinStat->ScrollBot, SCROLL_UP);
X  return OK;
X}
X
Xstatic Scroll(WinPtr, Top, Bottom, Direction)
X     WINDOW *WinPtr;
X     int Top, Bottom, Direction;
X{
X  int Step, SLine, DLine, Col;
X  char *TLine, *TLRLine;
X  short *TATTRS, *TLRATTRS;
X  struct WindowState *WinStat;
X  
X  if(!(WinStat = (struct WindowState *)WinPtr->_WinStat))
X    return ERR;
X  
X  /* Store pointers to line that will be lost */
X  if(Direction == SCROLL_UP) {
X    Step = +1;
X    DLine = Top;
X    SLine = Top + Step;
X  } else {
X    Step = -1;
X    DLine = Bottom;
X    SLine = Bottom + Step;
X  }
X  TLine = WinStat->LnArry[DLine].Line;
X  TLRLine = WinStat->LnArry[DLine].LRLine;
X  TATTRS = WinStat->LnArry[DLine].ATTRS;
X  TLRATTRS = WinStat->LnArry[DLine].LRATTRS;
X  /* Move the lines */
X  for(;;) {
X    if((Direction == SCROLL_UP) && (DLine >= Bottom))
X      break;  /* Done */
X    if((Direction == SCROLL_DOWN) && (DLine <= Top))
X      break;  /* Done */
X    WinStat->LnArry[DLine].Line = WinStat->LnArry[SLine].Line;
X    WinStat->LnArry[DLine].LRLine = WinStat->LnArry[SLine].LRLine;
X    WinStat->LnArry[DLine].ATTRS = WinStat->LnArry[SLine].ATTRS;
X    WinStat->LnArry[DLine].LRATTRS = WinStat->LnArry[SLine].LRATTRS;
X    for(Col=0; Col <= WinStat->Window._maxx; Col++) {
X      WinStat->LnArry[DLine].ATTRS[Col] = WinStat->Window._attrs;
X      WinStat->LnArry[DLine].LRATTRS[Col] = 0;
X    }
X    SLine += Step;
X    DLine += Step;
X  }
X  /* Blank the Temp line */
X  memset(TLine, ' ', WinStat->Window._maxx+1);
X  memset(TLRLine, 0, WinStat->Window._maxx+1);
X  for(Col=0; Col <= WinStat->Window._maxx; Col++) {
X    TATTRS[Col] = WinStat->Window._attrs;
X    TLRATTRS[Col] = 0;
X  }
X  /* move in temp line */
X  WinStat->LnArry[DLine].Line = TLine;
X  WinStat->LnArry[DLine].LRLine = TLRLine;
X  WinStat->LnArry[DLine].ATTRS = TATTRS;
X  WinStat->LnArry[DLine].LRATTRS = TLRATTRS;
X  
X  return OK;
X}
X
Xwsetscrreg(WinPtr, top, bottom)
X     WINDOW *WinPtr;
X     short top, bottom;
X{
X  struct WindowState *WinStat;
X  
X  if(!(WinStat = (struct WindowState *)WinPtr->_WinStat))
X    return ERR;
X  WinStat->ScrollTop = top;
X  WinStat->ScrollBot = bottom;
X  return OK;
X}
X
Xscrollok(WinPtr, flag)
X     WINDOW *WinPtr;
X     int flag;
X{
X  WinPtr->_scroll = (flag) ? TRUE : FALSE;
X  return OK;
X}
X
X/*
X *  Simple implementation of wnoutrefresh() and doupdate()
X *
X * Date: 8th Oct 1990
X *
X * Author: SJR
X *
X */
X
Xwnoutrefresh(WinPtr)
X     WINDOW *WinPtr;
X{
X  struct RefreshElement *NewRefEl;
X  
X  if(!(NewRefEl = (struct RefreshElement *)
X       malloc(sizeof(struct RefreshElement))))
X    return ERR;
X  
X  /* Fill the new element in */
X  NewRefEl->Next = (struct RefreshElement *)NULL;
X  NewRefEl->WinPtr = WinPtr;
X  
X  /* Add to start of refresh list */
X  if(HeadRefreshList)
X    NewRefEl->Next = HeadRefreshList;
X  HeadRefreshList = NewRefEl;
X}
X
Xdoupdate()
X{
X  struct RefreshElement *ElPtr;
X  void ZapRElList();
X  
X  ElPtr = HeadRefreshList;
X  while(ElPtr) {
X    if(wrefresh(ElPtr->WinPtr) == ERR)
X      return ERR;
X    ElPtr = ElPtr->Next;
X  }
X  ZapRElList(HeadRefreshList);
X  HeadRefreshList = (struct RefreshElement *)NULL;
X  
X  return OK;
X}
X
Xstatic void ZapRElList(ElPtr)
X     struct RefreshElement *ElPtr;
X{
X  if(!ElPtr)
X    return;
X  if(ElPtr->Next)
X    ZapRElList(ElPtr->Next);  /* Recurse my boy */
X  free(ElPtr);
X}
X
Xstatic void Optimise(LinePtr)
X     struct LineElement *LinePtr;
X{
X  int i;
X  
X  if(!LinePtr->Touched)
X    return;
X  for(i=LinePtr->StartCol; i<=LinePtr->EndCol; i++) {
X    if((LinePtr->Line[i] != LinePtr->LRLine[i]) ||
X       (LinePtr->ATTRS[i] != LinePtr->LRATTRS[i]))
X      break;
X    LinePtr->StartCol++;
X  }
X  for(i=LinePtr->EndCol; i>=LinePtr->StartCol; i--) {
X    if((LinePtr->Line[i] != LinePtr->LRLine[i]) ||
X       (LinePtr->ATTRS[i] != LinePtr->LRATTRS[i]))
X      break;
X    LinePtr->EndCol--;
X  }
X  if(LinePtr->StartCol > LinePtr->EndCol)
X    LinePtr->Touched = FALSE;
X}
END_OF_FILE
if test 44718 -ne `wc -c <'src/curses.c'`; then
    echo shar: \"'src/curses.c'\" unpacked with wrong size!
fi
# end of 'src/curses.c'
fi
echo shar: End of archive 5 \(of 8\).
cp /dev/null ark5isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 8 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
Mail submissions (sources or binaries) to <amiga@uunet.uu.net>.
Mail comments to the moderator at <amiga-request@uunet.uu.net>.
Post requests for sources, and general discussion to comp.sys.amiga.misc.