/* * * 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 #include #include #include #include #include #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; LineNLines; 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; LineNLines; 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<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_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; LineNLines; 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_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; jLnArry[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; LineNLines; 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; LineNoNLines; 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; }