/* Things having to do with putting windows on the (virtual) display */ /* Copyright (c) 1983 University of Maryland Computer Science Department */ #include "win.h" #include "display.h" #include #include #include #ifdef SIGVTALRM /* 4.2BSD */ #define sigset(s,d) signal(s,d) #define sighold(s) sigblock(1<<((s)-1)) #define sigrelse(s) sigsetmask(sigblock(0)&~(1<<((s)-1))) #endif SIGVTALRM static TouchedDisp; /* True iff DispPut has been called */ /* Return the size of the screen */ Wscreensize (rows, cols) int *rows, *cols; { *rows = ScreenLength; *cols = ScreenWidth; return 0; } /* Refresh the display */ Wrefresh (SkipInputCheck) { register Win *w; register i; static inrefresh; /* to avoid recursive refresh, which just plain does not work! */ if (inrefresh) return 0; inrefresh++; if (!WindowsActive) { fprintf (stderr, "Bad call to Wrefresh() - windows not active\n"); fflush (stderr); inrefresh = 0; return -1; } #ifdef FIONREAD if (SkipInputCheck == 0 && ioctl (0, FIONREAD, &InputPending) == 0 && InputPending) { inrefresh = 0; return 0; /* Dont bother if input is pending */ } #endif FIONREAD if (SigMagic) { sighold (SIGTSTP); sighold (SIGINT); } if (ScreenGarbaged || LastRedisplayPaused) { LastRedisplayPaused = 0; for (i = 1; i <= ScreenLength; i++) WDclearline (i); for (w = WinList; w; w = w -> w_next) { if ((w -> w_status & WHIDDEN) == 0) WDoDump (w); } } else { i = TouchedDisp | WSetRealCursor | WBoxActive; for (w = WinList; w; w = w -> w_next) { if (w -> w_status & WHIDDEN) continue; if (w -> w_status & WDUMP || w -> w_textbuf -> b_nmodw) i++, WDoDump (w); } if (i == 0) /* Nothing changed */ goto out; } TouchedDisp = WBoxActive; if (WBoxActive) WBoxToggle (); WDUpdateScreen (MajorUpdate, SkipInputCheck); if (WBoxActive) WBoxToggle (); out: MajorUpdate = 0; inrefresh = 0; if (SigMagic) { sigrelse (SIGTSTP); sigrelse (SIGINT); } fflush (stdout); return 0; } /* Write contents of window w to virtual screen */ static WDoDump (w) register Win *w; { register Ch *wt, *ww; register i, j; register Buf *b = w -> w_textbuf; wt = b -> b_contents + w -> w_bstart.row * b -> b_ncols + w -> w_bstart.col; ww = w -> w_winbuf; for (i = 1; i <= w -> OYE; i++) { WDsetpos (w -> OYO + i, w -> OXO + 1); for (j = 0; j < w -> OXE; j++) { if (ww -> Mode & WINVIS) dspskip (1); else if (ww -> Mode & WBUF) dsputc (wt -> Char, wt -> Mode ^ ww -> Mode); else dsputc (ww -> Char, ww -> Mode); wt++, ww++; } wt += b -> b_ncols - /* w -> OXE */ j; } if ((w -> w_status & WCURSOR) == 0) {/* Put up a cursor */ i = w -> IYO + w -> w_cursor.row; j = w -> IXO + w -> w_cursor.col; if (((w -> w_winbuf + i * w -> OXE + j) -> Mode & WINVIS) == 0) { WDsetpos (w -> OYO + i + 1, w -> OXO + j + 1); dspxor (WBLINK|WINVERSE); } } w -> w_status &= ~WDUMP; if (b -> b_nmodw == -1) b -> b_nmodw = b -> b_nwins - 1; else if (b -> b_nmodw) b -> b_nmodw--; } /* Put up the character at position row, col, possibly with cursor */ /* row, col should already have w -> IYE, w -> IXE added if needed */ WDispPut (w, row, col, curs) register Win *w; register row, col, curs; { register Ch *p; if (w -> w_status & WHIDDEN) return; p = w -> w_winbuf + row * w -> OXE + col; if (p -> Mode & WINVIS) return; WDsetpos (row + w -> OYO + 1, col + w -> OXO + 1); curs = curs ? WBLINK|WINVERSE : 0; if (p -> Mode & WBUF) { register Buf *b; curs ^= p -> Mode; b = w -> w_textbuf; p = b -> b_contents + (w -> w_bstart.row + row) * b -> b_ncols + w -> w_bstart.col + col; } dsputc (p -> Char, p -> Mode ^ curs); TouchedDisp++; } /* THIS FUNCTION COULD BE SUBSUMED BY THE LastRedisplayPaused VARIABLE */ /* Erase visible portions of window w from display */ WErase (w) register Win *w; { register Ch *wp; register i, j; if (w -> w_status & WHIDDEN)/* No need to erase */ return; wp = w -> w_winbuf; for (i = 1; i <= w -> OYE; i++) { WDsetpos (w -> OYO + i, w -> OXO + 1); for (j = 0; j < w -> OXE; j++) { if (wp++ -> Mode & WINVIS) dspskip (1); else dsputc (' ', 0); } } TouchedDisp++; } /* Toggle the box on the virtual display (write it if it's not there, remove it if it is). */ static WBoxToggle () { register i, j; WDsetpos (j = WBox.yorigin + 1, WBox.xorigin + 1); for (i = 0; i < WBox.xextent; i++) dspxor (WINVERSE); for (i = 2; i < WBox.yextent; i++) { WDsetpos (++j, WBox.xorigin + 1); dspxor (WINVERSE); if (WBox.xextent > 1) { dspskip (WBox.xextent - 2); dspxor (WINVERSE); } } if (WBox.yextent > 1) { WDsetpos (++j, WBox.xorigin + 1); for (i = 0; i < WBox.xextent; i++) dspxor (WINVERSE); } }