/* Copyright (c) 1993 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) * Copyright (c) 1987 Oliver Laumann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program (see the file COPYING); if not, write to the * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * **************************************************************** */ #include "rcs.h" RCS_ID("$Id: display.c,v 1.1.1.1 1993/08/15 18:32:56 nate Exp $ FAU") #include #include #include "config.h" #include "screen.h" #include "extern.h" static void CountChars __P((int)); static void PutChar __P((int)); static int BlankResize __P((int, int)); extern struct win *windows; extern int use_hardstatus; extern int MsgMinWait; extern int Z0width, Z1width; extern char *blank, *null; /* * tputs needs this to calculate the padding */ #ifndef NEED_OSPEED extern #endif /* NEED_OSPEED */ short ospeed; struct display *display, *displays; #ifndef MULTI struct display TheDisplay; #endif /* * The default values */ int defobuflimit = OBUF_MAX; #ifdef AUTO_NUKE int defautonuke = 0; #endif /* * Default layer management */ void DefProcess(bufp, lenp) char **bufp; int *lenp; { *bufp += *lenp; *lenp = 0; } void DefRedisplayLine(y, xs, xe, isblank) int y, xs, xe, isblank; { if (isblank == 0 && y >= 0) DefClearLine(y, xs, xe); } void DefClearLine(y, xs, xe) int y, xs, xe; { DisplayLine(null, null, null, blank, null, null, y, xs, xe); } /*ARGSUSED*/ int DefRewrite(y, xs, xe, doit) int y, xs, xe, doit; { return EXPENSIVE; } void DefSetCursor() { GotoPos(0, 0); } /*ARGSUSED*/ int DefResize(wi, he) int wi, he; { return -1; } void DefRestore() { InsertMode(0); ChangeScrollRegion(0, d_height - 1); KeypadMode(0); CursorkeysMode(0); SetAttrFont(0, ASCII); SetFlow(FLOW_NOW); } /* * Blank layer management */ struct LayFuncs BlankLf = { DefProcess, 0, DefRedisplayLine, DefClearLine, DefRewrite, DefSetCursor, BlankResize, DefRestore }; struct layer BlankLayer = { 0, 0, &BlankLf, 0 }; /*ARGSUSED*/ static int BlankResize(wi, he) int wi, he; { return 0; } /* * Generate new display */ struct display * MakeDisplay(uname, utty, term, fd, pid, Mode) char *uname, *utty, *term; int fd, pid; struct mode *Mode; { struct user **u; #ifdef MULTI if ((display = (struct display *)malloc(sizeof(*display))) == 0) return 0; bzero((char *) display, sizeof(*display)); #else if (displays) return 0; display = &TheDisplay; #endif display->_d_next = displays; displays = display; d_flow = 1; d_userfd = fd; d_OldMode = *Mode; Resize_obuf(); /* Allocate memory for buffer */ d_obufmax = defobuflimit; #ifdef AUTO_NUKE d_auto_nuke = defautonuke; #endif d_obufp = d_obuf; d_userpid = pid; #ifdef POSIX d_dospeed = (short) cfgetospeed(&d_OldMode.tio); #else # ifndef TERMIO d_dospeed = (short) d_OldMode.m_ttyb.sg_ospeed; # endif #endif debug1("New displays ospeed = %d\n", d_dospeed); strcpy(d_usertty, utty); strcpy(d_termname, term); if (!*(u = FindUserPtr(uname)) && UserAdd(uname, NULL, u)) { FreeDisplay(); return NULL; /* could not find or add user */ } d_user = *u; d_lay = &BlankLayer; d_layfn = BlankLayer.l_layfn; return display; } void FreeDisplay() { #ifdef MULTI struct display *d, **dp; for (dp = &displays; (d = *dp) ; dp = &d->_d_next) if (d == display) break; ASSERT(d); if (d_status_lastmsg) free(d_status_lastmsg); if (d_obuf) free(d_obuf); *dp = display->_d_next; free(display); #else /* MULTI */ ASSERT(display == displays); ASSERT(display == &TheDisplay); displays = 0; #endif /* MULTI */ display = 0; } /* * if the adaptflag is on, we keep the size of this display, else * we may try to restore our old window sizes. */ void InitTerm(adapt) int adapt; { ASSERT(display); d_top = d_bot = -1; PutStr(TI); PutStr(IS); /* Check for toggle */ if (IM && strcmp(IM, EI)) PutStr(EI); d_insert = 0; /* Check for toggle */ if (KS && strcmp(KS, KE)) PutStr(KE); d_keypad = 0; if (CCS && strcmp(CCS, CCE)) PutStr(CCE); d_cursorkeys = 0; PutStr(CE0); d_font = ASCII; if (adapt == 0) ResizeDisplay(d_defwidth, d_defheight); ChangeScrollRegion(0, d_height - 1); d_x = d_y = 0; Flush(); ClearDisplay(); debug1("we %swant to adapt all our windows to the display\n", (adapt) ? "" : "don't "); /* In case the size was changed by a init sequence */ CheckScreenSize((adapt) ? 2 : 0); } void FinitTerm() { ASSERT(display); ResizeDisplay(d_defwidth, d_defheight); DefRestore(); SetAttrFont(0, ASCII); d_x = d_y = -1; GotoPos(0, d_height - 1); AddChar('\n'); PutStr(TE); Flush(); } void INSERTCHAR(c) int c; { ASSERT(display); if (!d_insert && d_x < d_width - 1) { if (IC || CIC) { if (IC) PutStr(IC); else CPutStr(CIC, 1); RAW_PUTCHAR(c); return; } InsertMode(1); if (!d_insert) { RefreshLine(d_y, d_x, d_width-1, 0); return; } } RAW_PUTCHAR(c); } void PUTCHAR(c) int c; { ASSERT(display); if (d_insert && d_x < d_width - 1) InsertMode(0); RAW_PUTCHAR(c); } void PUTCHARLP(c) int c; { if (d_x < d_width - 1) { if (d_insert) InsertMode(0); RAW_PUTCHAR(c); return; } if (CLP || d_y != d_bot) { RAW_PUTCHAR(c); return; } d_lp_missing = 1; d_lp_image = c; d_lp_attr = d_attr; d_lp_font = d_font; } /* * RAW_PUTCHAR() is for all text that will be displayed. * NOTE: charset Nr. 0 has a conversion table, but c1, c2, ... don't. */ void RAW_PUTCHAR(c) int c; { ASSERT(display); if (d_font == '0') { AddChar(d_c0_tab[c]); } else AddChar(c); if (++d_x >= d_width) { if ((AM && !CLP) || d_x > d_width) { d_x -= d_width; if (d_y < d_height-1 && d_y != d_bot) d_y++; } } } static void PutChar(c) int c; { /* this PutChar for ESC-sequences only (AddChar is a macro) */ AddChar(c); } void PutStr(s) char *s; { if (display && s) { ospeed = d_dospeed; tputs(s, 1, PutChar); } } void CPutStr(s, c) char *s; int c; { if (display && s) { ospeed = d_dospeed; tputs(tgoto(s, 0, c), 1, PutChar); } } /* Insert mode is a toggle on some terminals, so we need this hack: */ void InsertMode(on) int on; { if (display && on != d_insert && IM) { d_insert = on; if (d_insert) PutStr(IM); else PutStr(EI); } } /* ...and maybe d_keypad application mode is a toggle, too: */ void KeypadMode(on) int on; { if (display && d_keypad != on && KS) { d_keypad = on; if (d_keypad) PutStr(KS); else PutStr(KE); } } void CursorkeysMode(on) int on; { if (display && d_cursorkeys != on && CCS) { d_cursorkeys = on; if (d_cursorkeys) PutStr(CCS); else PutStr(CCE); } } static int StrCost; /* ARGSUSED */ static void CountChars(c) int c; { StrCost++; } int CalcCost(s) register char *s; { ASSERT(display); if (s) { StrCost = 0; ospeed = d_dospeed; tputs(s, 1, CountChars); return StrCost; } else return EXPENSIVE; } void GotoPos(x2, y2) int x2, y2; { register int dy, dx, x1, y1; register int costx, costy; register int m; register char *s; int CMcost; enum move_t xm = M_NONE, ym = M_NONE; if (!display) return; x1 = d_x; y1 = d_y; if (x1 == d_width) if (CLP && AM) x1 = -1; /* don't know how the terminal treats this */ else x1--; if (x2 == d_width) x2--; dx = x2 - x1; dy = y2 - y1; if (dy == 0 && dx == 0) { return; } if (!MS && (d_attr || d_font != ASCII)) /* Safe to move ? */ SetAttrFont(0, ASCII); if (y1 < 0 /* don't know the y position */ || (y2 > d_bot && y1 <= d_bot) /* have to cross border */ || (y2 < d_top && y1 >= d_top)) /* of scrollregion ? */ { DoCM: if (HO && !x2 && !y2) PutStr(HO); else PutStr(tgoto(CM, x2, y2)); d_x = x2; d_y = y2; return; } /* Calculate CMcost */ if (HO && !x2 && !y2) s = HO; else s = tgoto(CM, x2, y2); CMcost = CalcCost(s); /* Calculate the cost to move the cursor to the right x position */ costx = EXPENSIVE; if (x1 >= 0) /* relativ x positioning only if we know where we are */ { if (dx > 0) { if (CRI && (dx > 1 || !ND)) { costx = CalcCost(tgoto(CRI, 0, dx)); xm = M_CRI; } if ((m = d_NDcost * dx) < costx) { costx = m; xm = M_RI; } /* Speedup: dx <= Rewrite() */ if (dx < costx && (m = Rewrite(y1, x1, x2, 0)) < costx) { costx = m; xm = M_RW; } } else if (dx < 0) { if (CLE && (dx < -1 || !BC)) { costx = CalcCost(tgoto(CLE, 0, -dx)); xm = M_CLE; } if ((m = -dx * d_LEcost) < costx) { costx = m; xm = M_LE; } } else costx = 0; } /* Speedup: Rewrite() >= x2 */ if (x2 + d_CRcost < costx && (m = (x2 ? Rewrite(y1, 0, x2, 0) : 0) + d_CRcost) < costx) { costx = m; xm = M_CR; } /* Check if it is already cheaper to do CM */ if (costx >= CMcost) goto DoCM; /* Calculate the cost to move the cursor to the right y position */ costy = EXPENSIVE; if (dy > 0) { if (CDO && dy > 1) /* DO & NL are always != 0 */ { costy = CalcCost(tgoto(CDO, 0, dy)); ym = M_CDO; } if ((m = dy * ((x2 == 0) ? d_NLcost : d_DOcost)) < costy) { costy = m; ym = M_DO; } } else if (dy < 0) { if (CUP && (dy < -1 || !UP)) { costy = CalcCost(tgoto(CUP, 0, -dy)); ym = M_CUP; } if ((m = -dy * d_UPcost) < costy) { costy = m; ym = M_UP; } } else costy = 0; /* Finally check if it is cheaper to do CM */ if (costx + costy >= CMcost) goto DoCM; switch (xm) { case M_LE: while (dx++ < 0) PutStr(BC); break; case M_CLE: CPutStr(CLE, -dx); break; case M_RI: while (dx-- > 0) PutStr(ND); break; case M_CRI: CPutStr(CRI, dx); break; case M_CR: PutStr(CR); d_x = 0; x1 = 0; /* FALLTHROUGH */ case M_RW: if (x1 < x2) (void) Rewrite(y1, x1, x2, 1); break; default: break; } switch (ym) { case M_UP: while (dy++ < 0) PutStr(UP); break; case M_CUP: CPutStr(CUP, -dy); break; case M_DO: s = (x2 == 0) ? NL : DO; while (dy-- > 0) PutStr(s); break; case M_CDO: CPutStr(CDO, dy); break; default: break; } d_x = x2; d_y = y2; } void ClearDisplay() { ASSERT(display); Clear(0, 0, d_width - 1, d_height - 1); } void Clear(xs, ys, xe, ye) int xs, ys, xe, ye; { int y, xxe; ASSERT(display); if (xs == d_width) xs--; if (xe == d_width) xe--; if (d_lp_missing && ys <= d_bot) { if (ye > d_bot || (ye == d_bot && xe == d_width - 1)) d_lp_missing = 0; } if (xe == d_width - 1 && ye == d_height - 1) { #ifdef AUTO_NUKE if (xs == 0 && ys == 0 && d_auto_nuke) NukePending(); #endif if (xs == 0 && ys == 0 && CL) { PutStr(CL); d_y = d_x = 0; return; } /* * Workaround a hp700/22 terminal bug. Do not use CD where CE * is also appropriate. */ if (CD && (ys < ye || !CE)) { GotoPos(xs, ys); PutStr(CD); return; } } xxe = d_width - 1; for (y = ys; y <= ye; y++, xs = 0) { if (y == ye) xxe = xe; if (xs == 0 && CB && (xxe != d_width - 1 || (d_x == xxe && d_y == y))) { GotoPos(xxe, y); PutStr(CB); continue; } if (xxe == d_width - 1 && CE) { GotoPos(xs, y); PutStr(CE); continue; } ClearLine(y, xs, xxe); } } /* * if cur_only > 0, we only redisplay current line, as a full refresh is * too expensive over a low baud line. */ void Redisplay(cur_only) int cur_only; { register int i, stop; ASSERT(display); DefRestore(); ClearDisplay(); stop = d_height; i = 0; if (cur_only > 0 && d_fore) { i = stop = d_fore->w_y; stop++; } else RedisplayLine(-1, 0, d_width - 1, 1); for (; i < stop; i++) RedisplayLine(i, 0, d_width - 1, 1); Restore(); SetCursor(); } void ScrollRegion(ys, ye, n) int ys, ye, n; { int i; int up; int oldtop, oldbot; int alok, dlok, aldlfaster; int missy = 0; ASSERT(display); if (n == 0) return; if (ys == 0 && ye == d_height - 1 && (n >= d_height || -n >= d_height)) { ClearDisplay(); return; } if (d_lp_missing) { if (d_bot > ye || d_bot < ys) missy = d_bot; else { missy = d_bot - n; if (missy>ye || missy= ye-ys+1) n = ye-ys+1; oldtop = d_top; oldbot = d_bot; if (d_bot != ye) ChangeScrollRegion(ys, ye); alok = (AL || CAL || (ye == d_bot && up)); dlok = (DL || CDL || (ye == d_bot && !up)); if (d_top != ys && !(alok && dlok)) ChangeScrollRegion(ys, ye); if (d_lp_missing && (oldbot != d_bot || (oldbot == d_bot && up && d_top == ys && d_bot == ye))) { FixLP(d_width - 1, oldbot); if (oldbot == d_bot) /* have scrolled */ { if (--n == 0) { ChangeScrollRegion(oldtop, oldbot); return; } } } aldlfaster = (n > 1 && ye == d_bot && ((up && CDL) || (!up && CAL))); if ((up || SR) && d_top == ys && d_bot == ye && !aldlfaster) { if (up) { GotoPos(0, ye); while (n-- > 0) PutStr(NL); /* was SF, I think NL is faster */ } else { GotoPos(0, ys); while (n-- > 0) PutStr(SR); } } else if (alok && dlok) { if (up || ye != d_bot) { GotoPos(0, up ? ys : ye+1-n); if (CDL && !(n == 1 && DL)) CPutStr(CDL, n); else for(i = n; i--; ) PutStr(DL); } if (!up || ye != d_bot) { GotoPos(0, up ? ye+1-n : ys); if (CAL && !(n == 1 && AL)) CPutStr(CAL, n); else for(i = n; i--; ) PutStr(AL); } } else { Redisplay(0); return; } if (d_lp_missing && missy != d_bot) FixLP(d_width - 1, missy); ChangeScrollRegion(oldtop, oldbot); if (d_lp_missing && missy != d_bot) FixLP(d_width - 1, missy); } void SetAttr(new) register int new; { register int i, old; if (!display || (old = d_attr) == new) return; d_attr = new; for (i = 1; i <= A_MAX; i <<= 1) { if ((old & i) && !(new & i)) { PutStr(UE); PutStr(SE); PutStr(ME); if (new & A_DI) PutStr(d_attrtab[ATTR_DI]); if (new & A_US) PutStr(d_attrtab[ATTR_US]); if (new & A_BD) PutStr(d_attrtab[ATTR_BD]); if (new & A_RV) PutStr(d_attrtab[ATTR_RV]); if (new & A_SO) PutStr(d_attrtab[ATTR_SO]); if (new & A_BL) PutStr(d_attrtab[ATTR_BL]); return; } } if ((new & A_DI) && !(old & A_DI)) PutStr(d_attrtab[ATTR_DI]); if ((new & A_US) && !(old & A_US)) PutStr(d_attrtab[ATTR_US]); if ((new & A_BD) && !(old & A_BD)) PutStr(d_attrtab[ATTR_BD]); if ((new & A_RV) && !(old & A_RV)) PutStr(d_attrtab[ATTR_RV]); if ((new & A_SO) && !(old & A_SO)) PutStr(d_attrtab[ATTR_SO]); if ((new & A_BL) && !(old & A_BL)) PutStr(d_attrtab[ATTR_BL]); } void SetFont(new) int new; { if (!display || d_font == new) return; d_font = new; if (new == ASCII) PutStr(CE0); else CPutStr(CS0, new); } void SetAttrFont(newattr, newcharset) int newattr, newcharset; { SetAttr(newattr); SetFont(newcharset); } void MakeStatus(msg) char *msg; { register char *s, *t; register int max, ti; if (!display) return; if (!d_tcinited) { debug("tc not inited, just writing msg\n"); AddStr(msg); AddStr("\r\n"); Flush(); return; } if (!use_hardstatus || !HS) { max = d_width; if (CLP == 0) max--; } else max = WS; if (d_status) { if (!d_status_bell) { ti = time((time_t *) 0) - d_status_time; if (ti < MsgMinWait) sleep(MsgMinWait - ti); } RemoveStatus(); } for (s = t = msg; *s && t - msg < max; ++s) if (*s == BELL) PutStr(BL); else if ((unsigned char)*s >= ' ' && *s != 0177) *t++ = *s; *t = '\0'; if (t > msg) { if (t - msg >= d_status_buflen) { char *buf; if (d_status_lastmsg) buf = realloc(d_status_lastmsg, t - msg + 1); else buf = malloc(t - msg + 1); if (buf) { d_status_lastmsg = buf; d_status_buflen = t - msg + 1; } } if (t - msg < d_status_buflen) strcpy(d_status_lastmsg, msg); d_status = 1; d_status_len = t - msg; d_status_lastx = d_x; d_status_lasty = d_y; if (!use_hardstatus || !HS) { debug1("using STATLINE %d\n", STATLINE); GotoPos(0, STATLINE); SetAttrFont(A_SO, ASCII); InsertMode(0); AddStr(msg); d_x = -1; } else { debug("using HS\n"); SetAttrFont(0, ASCII); InsertMode(0); CPutStr(TS, 0); AddStr(msg); PutStr(FS); } Flush(); (void) time(&d_status_time); } } void RemoveStatus() { struct win *p; if (!display) return; if (!d_status) return; /* * UGLY HACK ALERT - this should NOT be in display.c * We need to find the window that caused an activity or bell * message, to reenable this function there. */ for (p = windows; p; p = p->w_next) { if (p->w_display != display) continue; if (p->w_monitor == MON_MSG) { debug1("RemoveStatus clearing monitor win %d\n", p->w_number); p->w_monitor = MON_DONE; } if (p->w_bell == BELL_MSG) { debug1("RemoveStatus clearing bell win %d\n", p->w_number); p->w_bell = BELL_DONE; } } d_status = 0; d_status_bell = 0; if (!use_hardstatus || !HS) { GotoPos(0, STATLINE); RefreshLine(STATLINE, 0, d_status_len - 1, 0); GotoPos(d_status_lastx, d_status_lasty); } else { SetAttrFont(0, ASCII); PutStr(DS); } SetCursor(); } void RefreshLine(y, from, to, isblank) int y, from, to, isblank; { ASSERT(display); debug2("RefreshLine %d %d", y, from); debug2(" %d %d\n", to, isblank); if (isblank == 0 && CE && to == d_width - 1) { GotoPos(from, y); PutStr(CE); isblank = 1; } RedisplayLine(y, from, to, isblank); } void FixLP(x2, y2) register int x2, y2; { int oldattr = d_attr, oldfont = d_font; ASSERT(display); GotoPos(x2, y2); SetAttrFont(d_lp_attr, d_lp_font); PUTCHAR(d_lp_image); d_lp_missing = 0; SetAttrFont(oldattr, oldfont); } void DisplayLine(os, oa, of, s, as, fs, y, from, to) int from, to, y; register char *os, *oa, *of, *s, *as, *fs; { register int x; int last2flag = 0, delete_lp = 0; ASSERT(display); ASSERT(y >= 0 && y < d_height); ASSERT(from >= 0 && from < d_width); ASSERT(to >= 0 && to < d_width); if (!CLP && y == d_bot && to == d_width - 1) if (d_lp_missing || s[to] != os[to] || as[to] != oa[to] || of[to] != fs[to]) { if ((IC || IM) && from < to) { to -= 2; last2flag = 1; d_lp_missing = 0; } else { to--; delete_lp = (CE || DC || CDC); d_lp_missing = (s[to] != ' ' || as[to] || fs[to]); d_lp_image = s[to]; d_lp_attr = as[to]; d_lp_font = fs[to]; } } else to--; for (x = from; x <= to; ++x) { if (x || d_x != d_width || d_y != y - 1) { if (x < to || x != d_width - 1 || s[x + 1] == ' ') if (s[x] == os[x] && as[x] == oa[x] && of[x] == fs[x]) continue; GotoPos(x, y); } SetAttr(as[x]); SetFont(fs[x]); PUTCHAR(s[x]); } if (to == d_width - 1 && y < d_height - 1 && s[to + 1] == ' ') GotoPos(0, y + 1); if (last2flag) { GotoPos(x, y); SetAttr(as[x + 1]); SetFont(fs[x + 1]); PUTCHAR(s[x + 1]); GotoPos(x, y); SetAttr(as[x]); SetFont(fs[x]); INSERTCHAR(s[x]); } else if (delete_lp) { if (DC) PutStr(DC); else if (CDC) CPutStr(CDC, 1); else if (CE) PutStr(CE); } } void SetLastPos(x,y) int x,y; { ASSERT(display); d_x = x; d_y = y; } int ResizeDisplay(wi, he) int wi, he; { ASSERT(display); debug2("ResizeDisplay: to (%d,%d).\n", wi, he); if (d_width == wi && d_height == he) { debug("ResizeDisplay: No change\n"); return 0; } if (CWS) { debug("ResizeDisplay: using WS\n"); PutStr(tgoto(CWS, wi, he)); ChangeScreenSize(wi, he, 0); return 0; } else if (CZ0 && (wi == Z0width || wi == Z1width)) { debug("ResizeDisplay: using Z0/Z1\n"); PutStr(wi == Z0width ? CZ0 : CZ1); ChangeScreenSize(wi, d_height, 0); return (he == d_height) ? 0 : -1; } return -1; } void ChangeScrollRegion(newtop, newbot) int newtop, newbot; { if (display == 0) return; if (CS == 0) { d_top = 0; d_bot = d_height - 1; return; } if (d_top == newtop && d_bot == newbot) return; debug2("ChangeScrollRegion: (%d - %d)\n", newtop, newbot); PutStr(tgoto(CS, newbot, newtop)); d_top = newtop; d_bot = newbot; d_y = d_x = -1; /* Just in case... */ } /* * Layer creation / removal */ int InitOverlayPage(datasize, lf, block) int datasize; struct LayFuncs *lf; int block; { char *data; struct layer *newlay; RemoveStatus(); debug3("Entering new layer display %#x d_fore %#x oldlay %#x\n", (unsigned int)display, (unsigned int)d_fore, (unsigned int)d_lay); if ((newlay = (struct layer *)malloc(sizeof(struct layer))) == 0) { Msg(0, "No memory for layer struct"); return(-1); } data = 0; if (datasize) { if ((data = malloc(datasize)) == 0) { free(newlay); Msg(0, "No memory for layer data"); return(-1); } bzero(data, datasize); } newlay->l_layfn = lf; newlay->l_block = block | d_lay->l_block; newlay->l_data = data; newlay->l_next = d_lay; if (d_fore) { d_fore->w_lay = newlay; /* XXX: CHECK */ d_fore->w_active = 0; /* XXX: CHECK */ } d_lay = newlay; d_layfn = newlay->l_layfn; Restore(); return(0); } void ExitOverlayPage() { struct layer *oldlay; debug3("Exiting layer display %#x fore %#x d_lay %#x\n", (unsigned int)display, (unsigned int)d_fore, (unsigned int)d_lay); oldlay = d_lay; if (oldlay->l_data) free(oldlay->l_data); d_lay = oldlay->l_next; d_layfn = d_lay->l_layfn; free(oldlay); if (d_fore) d_fore->w_lay = d_lay; /* XXX: Is this necessary ? */ Restore(); SetCursor(); } /* * Output buffering routines */ void AddStr(str) char *str; { register char c; ASSERT(display); while ((c = *str++)) AddChar(c); } void AddStrn(str, n) char *str; int n; { register char c; ASSERT(display); while ((c = *str++) && n-- > 0) AddChar(c); while (n-- > 0) AddChar(' '); } void Flush() { register int l; register char *p; ASSERT(display); l = d_obufp - d_obuf; debug1("Flush(): %d\n", l); ASSERT(l + d_obuffree == d_obuflen); if (l == 0) return; if (d_userfd < 0) { d_obuffree += l; d_obufp = d_obuf; return; } p = d_obuf; if (fcntl(d_userfd, F_SETFL, 0)) debug1("Warning: DELAY fcntl failed: %d\n", errno); while (l) { register int wr; wr = write(d_userfd, p, l); if (wr <= 0) { if (errno == EINTR) continue; debug1("Writing to display: %d\n", errno); wr = l; } d_obuffree += wr; p += wr; l -= wr; } d_obuffree += l; d_obufp = d_obuf; if (fcntl(d_userfd, F_SETFL, FNDELAY)) debug1("Warning: NDELAY fcntl failed: %d\n", errno); } void freetty() { if (d_userfd >= 0) close(d_userfd); debug1("did freetty %d\n", d_userfd); d_userfd = -1; d_obufp = 0; d_obuffree = 0; if (d_obuf) free(d_obuf); d_obuf = 0; d_obuflen = 0; } /* * Asynchronous output routines by * Tim MacKenzie (tym@dibbler.cs.monash.edu.au) */ void Resize_obuf() { register int ind; ASSERT(display); if (d_obuflen && d_obuf) { ind = d_obufp - d_obuf; d_obuflen += GRAIN; d_obuffree += GRAIN; d_obuf = realloc(d_obuf, d_obuflen); } else { ind = 0; d_obuflen = GRAIN; d_obuffree = GRAIN; d_obuf = malloc(d_obuflen); } if (!d_obuf) Panic(0, "Out of memory"); d_obufp = d_obuf + ind; debug1("ResizeObuf: resized to %d\n", d_obuflen); } #ifdef AUTO_NUKE void NukePending() {/* Nuke pending output in current display, clear screen */ register int len; int oldfont = d_font, oldattr = d_attr, oldtop = d_top, oldbot = d_bot; int oldkeypad = d_keypad, oldcursorkeys = d_cursorkeys; len = d_obufp - d_obuf; debug1("NukePending: nuking %d chars\n", len); /* Throw away any output that we can... */ # ifdef POSIX tcflush(d_userfd, TCOFLUSH); # else # ifdef TCFLSH (void) ioctl(d_userfd, TCFLSH, (char *) 1); # endif # endif d_obufp = d_obuf; d_obuffree += len; d_top = d_bot = -1; PutStr(TI); PutStr(IS); /* Turn off all attributes. (Tim MacKenzie) */ if (ME) PutStr(ME); else { PutStr(SE); PutStr(UE); } /* Check for toggle */ if (IM && strcmp(IM, EI)) PutStr(EI); d_insert = 0; /* Check for toggle */ if (KS && strcmp(KS, KE)) PutStr(KE); d_keypad = 0; if (CCS && strcmp(CCS, CCE)) PutStr(CCE); d_cursorkeys = 0; PutStr(CE0); d_font = ASCII; d_attr = 0; ChangeScrollRegion(oldtop, oldbot); SetAttrFont(oldattr, oldfont); KeypadMode(oldkeypad); CursorkeysMode(oldcursorkeys); if (CWS) { debug("ResizeDisplay: using WS\n"); PutStr(tgoto(CWS, d_width, d_height)); } else if (CZ0 && (d_width == Z0width || d_width == Z1width)) { debug("ResizeDisplay: using Z0/Z1\n"); PutStr(d_width == Z0width ? CZ0 : CZ1); } } #endif /* AUTO_NUKE */